Re: Defining a cast on a templated class
On Nov 14, 4:40 pm, Michael DOUBEZ <michael.dou...@free.fr> wrote:
Alf P. Steinbach a =E9crit :
* 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.
Wow. Thanks. I guess I gotta study the boost libraries.
#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();}
I suppose the above call can be turned into:
inline operator T ()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);
}
From a basic analysis (correct me if I'm wrong) it seems that the
value is computed only when referenced (and is recomputed each time
it's referenced). Is this correct?
Dang, and I was going to implement some crazy updating code for
this...
Anyway I recently learned that ?: can't be overloaded, so I'll have to
do some other crazy things in order to handle conditionals. If ! can
be overloaded like the above (such that !!(foo) returns either 1 or 0,
regardless if foo is 0, 1, 42, or 1838596) possibly I can simply
create a function like so:
template<class T>
cell<T> num_if(cell<T> c, cell<T> t, cell<T> e){
return !!(c) * t + !(c) * e;
}
Of course a better approach would be to create a new class based on
the cell class, I suppose.