更新: conditional explicit已进入C ++ 20草案。 more on cppreference
cppreference std::tuple constructor page有一堆C ++ 17注释说:
此构造函数为
而言为假explicit
当且仅当std::is_convertible<const Ti&, Ti>::value
对于至少一个i
如何编写有条件显式的构造函数?我想到的第一种可能性是explicit(true)
,但这不是合法的语法。
enable_if
的尝试未成功:
// constructor is explicit if T is not integral
struct S {
template <typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
S(T) {}
template <typename T,
typename = typename std::enable_if<!std::is_integral<T>::value>::type>
explicit S(T) {}
};
错误:
error: ‘template<class T, class> S::S(T)’ cannot be overloaded
explicit S(T t) {}
答案 0 :(得分:14)
添加N4387: Improving pair and tuple, revision 3的提案有一个如何运作的示例:
考虑以下要使用的类模板A. 作为其他类型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; };
显示的构造函数都使用完美转发而且它们具有 基本上相同的签名除了一个是明确的, 另一个没有。此外,它们相互排斥。 换句话说:此组合适用于任何目标类型T. 和任何参数类型U像一个构造函数 显式或非显式(或根本没有构造函数)。
正如Praetorian所指出的那样libstdc++ implements it。
如果我们相应地修改OP示例,它也可以工作:
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) {}
};
答案 1 :(得分:5)
似乎与大多数编译器一起使用的一种方法是在其中一个函数中添加一个伪参数,使它们略有不同。
// 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");
}
使用MSVC 2015进行编译。