I have a template <bool P> class Foo
with lots of code in it. I want to be able to convert Foo<true>
's into Foo<false>
's, i.e. have an operator Foo<false>()
method. But the compiler doesn't like such a method existing for Foo, it only likes it for Foo<true>
, and gives a warning about how the "operator will not be called for implicit or explicit conversions" (GCC 5.4.x)
It doesn't seem like I can use SFINAE for this: std::enable_if
works with types; and a value-variant I tried out (where the true case has a value
rather than a type
member) didn't help either.
How can I get this operator to only be compiled for Foo<false>
(other than specializing Foo<false>
different and duplicating all of my code)?
My best attempt so far has been:
template <bool P> class Foo {
// etc. etc.
template <bool OtherValue>
operator Foo<OtherValue>()
{
static_assert(OtherValue, "You should not be using this conversion!");
// conversion code here
return Foo<false>(args,go,here);
}
}
You might use an helper struct and specilization to externalize your operator:
Demo
Using
P2 = P
delays the evaluation of theenable_if_t
to when the conversion operator is actually being used (instead of class instantiation).If we tried to simply write:
std::enable_if_t<P == true>
would be evaluated duringFoo<P>
's instantiation as there is no substitution occurring when the member functions are instantiated. The substitution is happening whenFoo
is instantiated - therefore SFINAE cannot take place (as there isn't any overload resolution set yet).By adding a
bool P2 = P
default parameter, we delay substitution to the instantiation of the conversion operator. This happens during overload resolution, so SFINAE can take place.This answer explains it better than I can: https://stackoverflow.com/a/13401982/598696
Your best attempt is actually not far off. You need to turn the conversion operator into a template so that SFINAE could work. Just enforce it only for the case
P
is true:The operator is a template with all parameters having default arguments. So it can be used. However, since the check is on
V
, we delay the verification of the operator until overload resolution. Then SFINAE eliminates it.