Here is a tag dispatch based way to solve your problem:
template<class T>
void doStuffHelper(const T& a, std::true_type can_copy_assign)
{
T x;
x=a;
printf("Hello\n");
}
template<class T>
void doStuffHelper(const T& a, std::false_type can_copy_assign)
{
printf("Goodbye\n");
}
template<class T>
void doStuff(const T& a)
{
return doStuffHelper( a, std::is_copy_assignable<T>() );
}
here, only the version that works is compiled. The name of can_copy_assign
exists merely for documentation -- the point is that I override based on std::is_copy_assignable<T>()
, and I use override dispatch to pick which implementation I am going to use.
In your code, the if
block becomes something like if(true)
. The else
clause of an if
block that is if(true)
still has to compile, which means the methods used have to be valid, even though they will never run.
The tag dispatch solution arranges it so that functions with the expected properties are compiled with the code that uses the properties.
Similar methods involving SFINAE can be used, but SFINAE has some annoying complications that mean it is usually best to avoid it, if possible.