[英]How to disable implicit constructor conversion, while allowing copy-initialization
Assuming we have something like: 假设我们有类似的东西:
class U {
...
}
and: 和:
class T {
T(const U&) { ... }
}
Now I can declare a variable like so: U foo;
现在我可以像这样声明一个变量:
U foo;
then T blah(foo);
然后
T blah(foo);
or T blah = foo
或者
T blah = foo
Personally I prefer the later. 我个人更喜欢后者。
Now, should I change the T copy constructor to: 现在,我应该将T拷贝构造函数更改为:
class T {
explicit T(const U&) { ... }
}
I can only declare a variable like: T blah(foo);
我只能声明一个变量:
T blah(foo);
T blah = foo;
will give me a compilation error about the impossibility to convert U to T. 会给我一个关于将U转换为T的不可能性的编译错误。
http://en.cppreference.com/w/cpp/language/explicit explains that behaviour with: "Specifies constructors and (since C++11) conversion operators that don't allow implicit conversions or copy-initialization ." http://en.cppreference.com/w/cpp/language/explicit解释了这种行为:“指定构造函数和(自C ++ 11以来)不允许隐式转换或复制初始化的转换运算符。”
Now, the folks I work for require that all our constructors are made explicit. 现在,我工作的人要求我们所有的构造函数都是明确的。 Being an old fart, I don't like changing my coding style too much and forget about T blah = ... style.
作为一个老屁,我不喜欢太多改变我的编码风格而忘记T blah = ...风格。
The question as such is this: "Is there a way to make a constructor explicit while allowing copy-initialization syntax?" 这样的问题是:“有没有办法在允许复制初始化语法的同时使构造函数显式化?”
There are very good reasons to make a constructor explicit, and most of the time, you do want to make it explicit. 将构造函数显式化是有充分理由的,而且大多数情况下,您确实希望将其显式化。
Under those instances, I thought I could do something along the line of: 在这些情况下,我认为我可以做以下事情:
class T {
template<typename = V>
T(const V&) = delete;
T(const U&) { ... }
}
Which would be a catch-all constructor forbidding all conversion but the one I actually want. 这将是一个全能的构造函数,禁止所有转换但我真正想要的转换。
Was wondering if there was some trick I could use. 想知道是否有一些我可以使用的技巧。
Thanks 谢谢
Edit: corrected the typo as pointed by Matt McNabb answer. 编辑:纠正了Matt McNabb回答的错字。 thanks
谢谢
T blah = U();
gives the error because, as you correctly explain, copy-initialization calls for implicit conversion of U
to T
; 给出错误,因为正如您正确解释的那样,复制初始化调用将
U
隐式转换为T
; but you have marked the constructor explicit
. 但是你已经
explicit
标记了构造explicit
。 (Note: this is not a copy constructor) (注意:这不是复制构造函数)
Explicit conversion would look like T blah = T(U());
显式转换看起来像
T blah = T(U());
and this should work with no errors. 这应该没有错误。
T blah(U());
is a function declaration (look up most vexing parse ). 是一个函数声明(查找最令人烦恼的解析 )。 You probably didn't actually try to use
blah
as if it were an object, in your test case, otherwise you would have noticed this problem. 在你的测试用例中,你可能实际上并没有尝试使用
blah
,就好像它是一个对象,否则你会注意到这个问题。
Moving onto your question: 转到你的问题:
Is there a way to make a constructor explicit while allowing copy-initialization syntax?
有没有办法在允许复制初始化语法的同时使构造函数显式化?
There is not, as explained by the exact text you quoted about explicit
: 没有,正如你引用的关于
explicit
的确切文字所解释的那样:
Specifies constructors [...] that don't allow [...] copy-initialization.
指定不允许复制初始化的构造函数[...]。
You'll have to switch to direct or braced initialization. 您必须切换到直接或支持初始化。 IMHO that's a good thing anyway, copy-initialization is cumbersome and only good for avoiding MVPs;
恕我直言,这是一件好事,复制初始化很麻烦,只对避免MVP有好处; but now that we can avoid MVPs using braced initialization, it's no longer necessary at all.
但现在我们可以避免使用支撑初始化的MVP,它根本不再需要。
You could use either of the following, which work because in all cases a T
is directly and explicitly initialized by the list element: 您可以使用以下任一方法,因为在所有情况下,
T
都由list元素直接显式初始化:
T blah{ U() };
T blah = T{ U() }; // redundant copy/move operation, probably elided
Note that T blah = { U() };
注意
T blah = { U() };
cannot be used here because that form of initialization (known as copy-list-initialization ) cannot use an explicit constructor. 这里不能使用,因为这种初始化形式(称为copy-list-initialization )不能使用显式构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.