【问题标题】:How to disable implicit constructor conversion, while allowing copy-initialization如何禁用隐式构造函数转换,同时允许复制初始化
【发布时间】:2015-07-13 09:54:45
【问题描述】:

假设我们有类似的东西:

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 回答所指出的错字。谢谢

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    T blah = U(); 给出错误,因为正如您正确解释的那样,复制初始化需要将 U 隐式转换为 T;但是您已将构造函数标记为explicit。 (注意:这不是复制构造函数)

    显式转换看起来像T blah = T(U());,这应该可以正常工作。

    T blah(U()); 是一个函数声明(查找most vexing parse)。在您的测试用例中,您可能实际上并没有尝试将blah 当作一个对象来使用,否则您会注意到这个问题。


    继续你的问题:

    有没有办法在允许复制初始化语法的同时使构造函数显式?

    没有,正如您引用的关于 explicit 的确切文字所解释的那样:

    指定不允许 [...] 复制初始化的构造函数 [...]。

    您必须切换到直接或支撑初始化。恕我直言,无论如何,这是一件好事,复制初始化很麻烦,而且只对避免 MVP 有好处;但是现在我们可以使用大括号初始化来避免 MVP,它根本就没有必要了。

    您可以使用以下任一方法,因为在所有情况下,T 都由列表元素直接且显式地初始化:

    T blah{ U() };
    T blah = T{ U() };  // redundant copy/move operation, probably elided
    

    请注意,此处不能使用T blah = { U() };,因为这种初始化形式(称为copy-list-initialization)不能使用显式构造函数。

    【讨论】:

    • T blah = { U() }; 不代表T blah = { T(U()) };。 Copy-list-initialization 甚至在概念上都不会构造一个临时的T
    • @T.C.好的,您能否将我的最后一段编辑为正确的(并在需要时修复任何其他术语)。我检查了编译器而不是标准,它拒绝了T blah = { U(); },因为构造函数是显式的,所以我认为这是因为必须创建T
    • 你是对的......我写信给快速试图概念化这个问题。我的实际用途是:U foo; T blah = foo;
    • @MattMcNabb 好的,已编辑。该标准只是在这种情况下直接禁止显式构造函数(即,如果重载决议选择了一个,则代码格式错误)。
    猜你喜欢
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2012-02-27
    相关资源
    最近更新 更多