Re: limiting a template class to certain types ?
Alf P. Steinbach wrote:
You could try
template <class T1,class T2>
typename boost::enable_if_c<
is_callable<T1>::value && is_callable<T2>::value,
Sum<T1,T2>
>::type
operator+(T1 t1,T2 t2) { return Sum<T1,T2>(t1,t2); }
which I believe is specifically what you're asking for.
However, for your chosen problem this leads to a little (contained)
combinatorial explosion: it answers the question but does not solve the
problem in a reasonable way, and that's because you're not asking about
the problem but about a particular non-working way to solve it.
That's a handy little tool. But you're right that it didn't quite
solve the problem. I still couldn't make the compiler figure out to do
the implicit cast.
Better to simply make sure that anything that can behave as a constant
has a value:
....
template< typename T > T valueOf( T const& x )
{ return x; }
template< typename T > T valueOf( Constant<T> const& x )
{ return static_cast<T>( x() ); } // Cast due to use of 'double'.
template <class T1, class T2> class Sum {
T1 t1; T2 t2;
public:
Sum(T1 _t1, T2 _t2) : t1(_t1), t2(_t2) { }
double operator()() const { return valueOf(t1) + valueOf(t2); }
};
template <class T1,class T2>
Sum<T1,T2> operator+(T1 t1,T2 t2) { return Sum<T1,T2>(t1,t2); }
Well, I'm not quite sure what you're doing there with the static_cast.
But I did realize I was going about it all wrong. My solution is to
define
template <class T,bool b=is_callable<T>::value> struct callable_cast {
typedef Constant<T> type;
};
template <class T> struct callable_cast<T,true> {
typedef T type;
};
Then, I can write (using a helper to maybe improve readability)
template <class T1,class T2> struct sum_result {
typedef Sum<typename callable_cast<T1>::type,
typename callable_cast<T2>::type> type;
};
template <class T1,class T2> typename sum_result<T1,T2>::type
operator+(T1 t1,T2 t2) {
return typename sum_result<T1,T2>::type(t1,t2);
}
This way, the overloaded operator can take whatever it wants, and the
cast becomes explicit. My interest in this problem came from trying to
make a toy version of boost::lambda to see how it worked (cf. a post
from 4-5 days earlier), and realizing that I needed to enclose all my
literals in "make_constant(...)" so that they would cooperate with my
operators since they could only act on placeholder expressions. This
should solve that particular problem (now I just need to figure out how
to get the reference- and const-casting to work...)
Thank you all very much!
steve