Search code examples
c++c++11visual-studio-2012enable-if

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)
}

Solution

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