Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Two versions of enable_if usage work differently

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading