【问题标题】:Why does this snippet using uniform initialization compile with g++4.6 but not g++4.7?为什么这个使用统一初始化的代码片段使用 g++4.6 而不是 g++4.7 编译?
【发布时间】:2012-09-01 01:16:37
【问题描述】:

注意派生使用C++11统一初始化语法调用基类构造函数。

class base
{
    protected:
        base()
        {}
};

class derived : public base
{
    public:
        derived()
            : base{} // <-- Note the c++11 curly brace syntax
                     // using uniform initialization. Change the
                     // braces to () and it works.
        {}
};

int main()
{
    derived d1;

    return 0;
}

g++4.6 编译这个,但是 g++4.7 没有:

$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context

发生了什么事?

更新 1:它也可以使用 clang++-3.1 编译而没有警告
更新 2:Looks like a compiler bug for sure. 它显然已在 GCC 4.7.3 中修复。

【问题讨论】:

  • 与大括号初始化器有关的编译器错误在 GCC 中并不少见。
  • @Als 当然...因为 gcc-4.3.4 没有初始化列表。
  • @DrTwox 我只是想知道 g++4.7.x 是否将此表达式 derived() : base {} {} 解释为 derived() : base(base{}) {}。要创建临时文件,需要公开访问base::base()。我没有 g++4.7.x,所以如果将临时更改为我的提案 - 那么如果这是错误就很清楚了。
  • @PiotrNycz:关于:base(base{}) 理论,我用-fno-elide-constructors 编译了代码,没有额外调用复制构造函数或析构函数。所以这里暂时不涉及。
  • @cuabanana - 据我所知,它是有效的 C++11 语法。

标签: c++ gcc c++11 g++ uniform-initialization


【解决方案1】:

这可能是因为在 4.7 C11 版本中添加了显式覆盖控制。

【讨论】:

  • 您能详细说明一下吗?您的意思是 C++11,而不是 C11?使用统一初始化时,为什么以及如何显式覆盖控制干扰调用基类的构造函数?
【解决方案2】:

用 icpc 编译它(intel 编译器测试版本 11.1 -> 12.1)给出:

-bash-3.2$ icpc -std=c++0x test.c 
test.c(15): error: expected a declaration
          {}
          ^

test.c(12): error: expected a "("
              : base{} // <-- Note the c++11 curly brace syntax
                    ^

compilation aborted for test.c (code 2)

编辑:但话又说回来,c++11 也没有在 icpc 中完全实现 http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/

与 g++ 相同 http://gcc.gnu.org/gcc-4.7/cxx0x_status.html

这清楚地表明它仍处于实验阶段,因此很可能存在错误。

【讨论】:

  • 统一初始化对基类型完全有效。
【解决方案3】:

我发现了这个:

“草案说,初始化引用的初始化列表不是通过直接绑定来完成的,而是首先从初始化列表中的元素构造一个临时对象,然后将目标引用绑定到该临时对象”

因此,base{} 创建的临时对象是通过受保护的构造函数完成的,这可能会令人窒息。

【讨论】:

  • base 是一个... base。这不是参考。这无关紧要。
【解决方案4】:

Paolo Carlini,GCC/libstdc++ 贡献者,confirmed it is a bug/regression

【讨论】:

    猜你喜欢
    • 2019-11-15
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 2020-02-02
    • 1970-01-01
    • 2014-09-20
    相关资源
    最近更新 更多