Re: Defining a cast on a templated class
Alf P. Steinbach a 9crit :
* alan:
I'm creating a sort-of "wrapper" class which (partly) acts like a
variable. Something like:
template<class t>
class cell{
t curval;
public:
/*public for debugging only - will be private in final version*/
inline cell<t>& set_value(t v){ curval = v; return *this;}
inline t get_value(){ return curval;}
/*actual public interface*/
/*assign to this value*/
inline cell<t>& operator=(t v){ return set_value(v);}
};
[snip: answered]
Basically the cell<> class would be like a spreadsheet cell - when I
assign a formula into it, its value will be automatically updated if
any of the cells in the formula are updated.
The way I intend to implement it is, I extend +-*/ and ?: so that if
any cells are in any parameters, they will instead return a new cell
which registers itself to the input cells. Something like:
template<class t>
cell<t>& operator+(cell<t> v1, t v2){
sum_cell<t> *sum = new sum_cell<t>(v2);
sum.register_yourself_to(v1); //when v1 is update()d, sum's update()
method is called
return (cell<t>&) *sum;
}
If there is already some existing library that does (in some form) the
above, please inform me. I suspect there already is, somehow I have a
feeling I've seen it before.
Perhaps look at the Open Office source?
It is straightforward to use boost::function0<T>(), boost::ref() and
boost::bind() to compose your elements.
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
#include <functional>
#include <cassert>
//use with boost::function0<T> to return constant value
template<class T>
T identity(const T& t)
{
return t;
}
template<class T>
class cell
{
public:
//ensure get_value() always work
cell<T>(const T& t=T())
{
set_value(t);
}
cell<T>& operator+=(cell<T>& c)
{
value= boost::bind(operation<std::plus<T> >,
*this,boost::ref(c));
return *this;
}
//make a const version to use when rhs is local
cell<T>& operator+=(const cell<T>& c)
{
value=boost::bind(operation<std::plus<T> >,
*this,c);
return *this;
}
inline T get_value()const{ return value();}
private:
//generic operation on two cell
template<typename Operator >
static T operation(const cell<T>& lhs,const cell<T>& rhs)
{
return Operator()(lhs.get_value(),rhs.get_value());
}
inline cell<T>& set_value(const T& v)
{
value = boost::bind(&identity<T>,v);
return *this;
}
boost::function0<T> value;
};
template<typename T>
cell<T> operator+(const cell<T>& lhs,const cell<T>& rhs)
{
cell<T> ret(lhs);
return ret+=rhs;
}
template<typename T>
cell<T> operator+(const cell<T>& lhs,cell<T>& rhs)
{
cell<T> ret(lhs);
return ret+=rhs;
}
typedef cell<int> icell;
int main()
{
icell a(1);
std::cout<<a.get_value()<<std::endl;
assert(a.get_value()==1);
icell b;
std::cout<<b.get_value()<<std::endl;
assert(b.get_value()==0);
b=3;
std::cout<<b.get_value()<<std::endl;
assert(b.get_value()==3);
icell c = a + b;
std::cout<<c.get_value()<<std::endl;
assert(c.get_value()==4);
b=5;
std::cout<<c.get_value()<<std::endl;
assert(c.get_value()==6);
c+=a;
std::cout<<c.get_value()<<std::endl;
assert(c.get_value()==7);
icell d=c+icell(2);
std::cout<<d.get_value()<<std::endl;
assert(d.get_value()==9);
}
Michael