条件标记为显式的构造函数
Constructor conditionally marked explicit
更新:条件显式已被纳入c++ 20草案。更多关于cppreference
cppreference std::tuple构造函数页面有一堆c++ 17注释,比如:
当且仅当
std::is_convertible<const Ti&, Ti>::value
对至少一个i
为假时,此构造函数为explicit
如何编写条件显式的构造函数?我想到的第一个可能是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) {}
添加了N4387:改进pair和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++实现它的方式。
如果我们相应地修改OPs的例子,它也可以工作:
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) {}
};
对于大多数编译器来说,似乎可行的一种方法是在其中一个函数中添加一个虚拟参数,使它们略有不同。
// 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");
}
相关文章:
- 将派生类的构造函数声明为父类的友元
- 隐式移动构造函数应为否,除非可能
- 将复制构造函数设置为private和=delete有什么区别
- 复制构造函数参数为0
- 将复制构造函数设置为默认值在继承自 QObject 时不起作用
- 构造函数解释为函数调用,并显式跳过移动构造函数
- 在父对象的构造函数中为子对象提供指向父对象的指针?
- 尝试将构造函数设置为 0 - c++ 的未处理异常
- LCOV 问题:奇怪的重复构造函数标记为未覆盖和函数未标记为已覆盖,即使它的行已被执行
- 在类的构造函数中为常量动态大小的数组赋值
- 我应该将编译器生成的构造函数标记为 constexpr 吗?
- 可以将构造函数复制为转换运算符
- 将具有默认值的构造函数定义为组合对象的私有字段
- 为什么智能指针不能在其构造函数中为我调用 new()?
- 在构造函数中为另一个相同类型的对象构造对象是个好主意吗
- g++将基构造函数错误为字段,并忽略它的参数
- 一个类的构造函数,为另一个类进行强制转换.将调用什么函数
- 确定抽象基类的构造函数是否为 noexcept
- 编译器何时将默认生成的构造函数标记为 noexcept
- C++ "没有合适的构造函数可以从<默认构造函数>转换为参数化构造函数