Constructor conditionally marked explicit

前端 未结 2 1256
借酒劲吻你
借酒劲吻你 2020-12-08 19:30

Update: conditional explicit has made it into the C++20 draft. more on cppreference

The cppreference std::tuple constructor page has a bunch of C++1

相关标签:
2条回答
  • 2020-12-08 20:15

    The proposal that added that N4387: Improving pair and tuple, revision 3 has an example of how it works:

    Consider the following class template A that is intended to be used as a wrapper for some other type T:

    #include <type_traits>
    #include <utility>
    
    template<class T>
    struct A {
      template<class U,
        typename std::enable_if<
          std::is_constructible<T, U>::value &&
          std::is_convertible<U, T>::value
        , bool>::type = false
      >
      A(U&& u) : t(std::forward<U>(u)) {}
    
     template<class U,
        typename std::enable_if<
          std::is_constructible<T, U>::value &&
          !std::is_convertible<U, T>::value
        , bool>::type = false
      >
      explicit A(U&& u) : t(std::forward<U>(u)) {}
    
      T t;
    };
    

    The shown constructors both use perfect forwarding and they have essentially the same signatures except for one being explicit, the other one not. Furthermore, they are mutually exclusively constrained. In other words: This combination behaves for any destination type T and any argument type U like a single constructor that is either explicit or non-explicit (or no constructor at all).

    As Praetorian points out this is exactly how libstdc++ implements it.

    If we modify the OPs example accordingly, it also works:

    struct S {
      template <typename T,
                typename std::enable_if< std::is_integral<T>::value, bool>::type = false>
      S(T) {}
    
      template <typename T,
                typename std::enable_if<!std::is_integral<T>::value, bool>::type = false>
      explicit S(T) {}
    };
    
    0 讨论(0)
  • 2020-12-08 20:15

    One way that seems to work with most compilers is to add a dummy parameter to one of the functions, to make them slightly different.

    // constructor is explicit if T is integral
    
    struct S {
      template <typename T,
                typename = typename std::enable_if<std::is_integral<T>::value>::type>
      S(T t) {}
    
      template <typename T,
                typename = typename std::enable_if<!std::is_integral<T>::value>::type,
                typename dummy = void>
      explicit S(T t) {}
    };
    
    int main()
    {
       S  s1(7);
    
       S  s2("Hello");    
    }
    

    Compiles with MSVC 2015.

    0 讨论(0)
提交回复
热议问题