user2019765 user2019765 - 19 days ago 5
C++ Question

enable_if and constructor with VS2012

I am trying to conditionally enable a constructor template. With a fully C++11-compliant compiler, I know how to do this using an extra default template argument. However, I need to support VS2012, which has std::enable_if but does not support defaulted function template arguments.

With C++11, I would write the following:

template<typename T>
struct Class
{
template<typename O,
typename = typename std::enable_if<std::is_convertible<O*, T*>::value>::type>
Class(O*) {}
};


I tried the following, but it gives an error C4336 and various follow-up errors:

template<typename T>
struct Class
{
template <typename O>
Class(O*, typename std::enable_if<std::is_convertible<O*, T*>::value>::type *= nullptr)
{
}
};


Is there any way to make this work with VS2012?

Addition:

The usage of the class would be as follows:

struct X { };
struct X2 : X { };
struct Y { };

struct Client
{
Client(Class<X> x) {}
Client(Class<Y> y) {}
};

void test() {
X2* x2;
Client client(x2); // error C2668: ambiguous call to overloaded function
// (without std::enable_if)
}

Answer

You are so close to the solution !

template<typename T>
struct Class
{
    template <typename O>
    Class(O*, typename std::enable_if<std::is_convertible<O*, T*>::value>::type * = nullptr)
    {
    }
};

Did you spot the difference ? *= inside the parameter list was parsed as the multiplication/assignment operator, not as a pointer type followed by a default argument. Hence, syntax errors.

This is because the C++ parser is specified to consume as many characters as possible when it forms a token (the so-called Maximum Munch Rule). Adding a space splits it into two separate tokens, as intended.

Comments