假设我们有类似的东西:
class U {
...
}
和
class T {
T(const U&) { ... }
}
现在我可以像这样声明一个变量:
U foo;
然后T blah(foo);
或T blah = foo
我个人更喜欢后者。
现在,我应该将T拷贝构造函数更改为:
class T {
explicit T(const U&) { ... }
}
我只能声明一个变量:
T blah(foo);
T blah = foo;
会给我一个关于将U转换为T的不可能性的编译错误。
http://en.cppreference.com/w/cpp/language/explicit解释了这种行为: “指定构造函数和(自C ++ 11以来)不允许隐式转换或复制初始化的转换运算符。”
现在,我工作的人要求我们所有的构造函数都是明确的。 作为一个老屁,我不喜欢太多改变我的编码风格而忘记T blah = ...风格。
这样的问题是: “有没有办法在允许复制初始化语法的同时使构造函数显式化?”
有很好的理由让构造函数显式化,而且大多数时候,你做想要明确它。
在这些情况下,我认为我可以按照以下方式做点什么:
class T {
template<typename = V>
T(const V&) = delete;
T(const U&) { ... }
}
这将是一个全能的构造函数,禁止所有转换,但我真正想要的转换。
想知道是否有一些我可以使用的技巧。
由于
编辑:修正了Matt McNabb回答中指出的拼写错误。感谢
答案 0 :(得分:3)
T blah = U();
给出错误,因为正如您正确解释的那样,复制初始化调用将U
隐式转换为T
;但是你已经标记了构造函数explicit
。 (注意:这不是复制构造函数)
显式转换看起来像T blah = T(U());
,这应该没有错误。
T blah(U());
是一个函数声明(查找most vexing parse)。在你的测试用例中,你可能并没有真正尝试使用blah
,就好像它是一个对象一样,否则你会注意到这个问题。
转到你的问题:
有没有办法在允许复制初始化语法的同时使构造函数显式化?
正如您引用的关于explicit
的确切文字所解释的那样:
指定不允许复制初始化的构造函数。
您必须切换到直接或支持初始化。恕我直言,无论如何,复制初始化很麻烦,只对躲避MVP有好处;但现在我们可以避免使用支持初始化的MVP,它根本不再需要。
您可以使用以下任何一种方法,因为在所有情况下,T
都由list元素直接显式初始化:
T blah{ U() };
T blah = T{ U() }; // redundant copy/move operation, probably elided
请注意,此处不能使用T blah = { U() };
,因为这种初始化形式(称为 copy-list-initialization )不能使用显式构造函数。