I’m currently writing a generic vector template class (the geometric entity, not the container) with the following signature…
template< typename T, unsigned N >
class vector
{...}
… where T is an arithmetic type and N, the dimension. I would like to define the cross product as an overload of operator ^ (located inside class definition) and enable it only when N == 3. What I’ve have now is:
typename boost::lazy_enable_if_c< (N == 3), vector >::type
inline operator ^(const vector &rhs) const
{
vector ret;
ret(0) = val_[1] * rhs(2) - val_[2] * rhs(1);
ret(1) = val_[2] * rhs(0) - val_[0] * rhs(2);
ret(2) = val_[0] * rhs(1) - val_[1] * rhs(0);
return ret;
}
Unfortunately, instantiating this template with N != 3, even though operator ^ isn’t referenced, yields the following error:
error: no type named ‘type’ in ‘struct boost::lazy_enable_if_c < false, flare::math::vector < flare::math::fixed < short int, 8u >, 2u > >’
What am I doing wrong? Is there an alternative to boost::enable_if in such case?
Thank you very much.
The proximal cause of the error message is that, according to the docs, “The second argument of
lazy_enable_ifmust be a class type that defines a nested type namedtypewhenever the first parameter (the condition) is true.” That’s clearly not satisfied here (unless yourvectortype just happens to containtypedef something type;).You don’t need
lazy_...here. According to the docs, that’s only needed if the 2nd arg could be undefined (e.g. if the 2nd arg wastypename foo<T>::bar, and thebartype is not defined for all typesT).vector(which here meansvector<T, N>) will always be defined.So definitely try getting rid of
lazy_, or alternatively create a do-nothing traits classtemplate <typename T> struct nop { typedef T type; };and replace the 2nd arg tolazy_enable_if_cwithnop<vector>. But my guess is you’ve already tried the former at least. 🙂And now I see why that won’t work. According to the standard 14.7.1/1:
So anything that causes the class to be instantiated will try to instantiate declarations for all methods, which will fail when
N != 3. So it looks like you’ll need to use an always-present method that hands off to a function template instead. Don’t worry, any decent compiler will still be able to inline through this:This will work because the member function definitions are not instantiated unless they are actually called (or their addresses are taken etc.).