I cannot understand why do two versions of copy constructor work differently (because of enable_if).
template <typename Type>
struct Predicate : std::integral_constant<bool, true>
{
};
template <>
struct Predicate<int> : std::integral_constant<bool, false>
{
};
template <typename FooType>
struct Settings
{
Settings() {}
// Here it works fine
template <typename OtherFooType>
Settings(const Settings<OtherFooType>& other, std::enable_if_t<Predicate<OtherFooType>::value, int*> = 0) {}
// In this case enable_if does not work
//template <typename OtherFooType>
//Settings(typename std::enable_if<Predicate<OtherFooType>::value, const Settings<OtherFooType>&>::type other){}
};
int main()
{
Settings<float> f = Settings<char>();
return 0;
}
From my point of view, here enable_if is the SFINAE way to conditionally remove copy constructor. It should work in both cases. Maybe am I missing understaing of SFINAE?
>Solution :
In the second example the template parameter OtherFooType appears only left to the scope resolution operator :: in the function parameter.
Everything left of :: in a type specified by qualified name is a non-deduced context, meaning that the template argument for OtherFooType will not be deduced from the function parameter/argument pair.
As a consequence there is no way to deduce OtherFooType and so the constructor is always non-viable.
SFINAE doesn’t even matter since that would be relevant only when substitution happens after successful deduction.
Also, (specializations of) constructor templates are never copy constructors. These are converting constructors and a copy constructor will still be declared implicitly.