当前位置: 首页 > 知识库问答 >
问题:

G++7.1.0以后支持此构造函数中有保证的复制省略,但Clang++4.0以后不支持

酆茂才
2023-03-14

我一直试图生成一个类,它的成员是一个STD::数组,它的类型是不可复制的,我需要在构造函数中初始化它。关于这个问题的答案,我曾认为以下方法是可行的:

#include <array>
#include <utility>

class Foo {
public:
    Foo() {}
    Foo(const Foo& rhs) = delete;   
    Foo(Foo&& rhs) = delete;
};

template<size_t BufferSize>
class FooBuffer {
public:

    template<size_t... Is>
    FooBuffer(std::index_sequence<Is...>)
        : _buffer({{(static_cast<void>(Is), Foo{})...}})
    {
    }

    FooBuffer() : FooBuffer(std::make_index_sequence<BufferSize>{}) {}

private:    

    std::array<Foo,BufferSize> _buffer;

};

using namespace std;
int main(int, char **) {
    FooBuffer<10> foo;
}

根据Wandbox的说法,从GCC Version7.1.0到C++17或C++17(GNU)标志都是如此:

链接到GCC 7.1.0下的工作编译

prog.cc:18:5: error: call to implicitly-deleted copy constructor of 'std::array<Foo, 10UL>'
                : _buffer({{(static_cast<void>(Is), Foo{})...}})
                  ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:22:16: note: in instantiation of function template specialization 'FooBuffer<10>::FooBuffer<0, 1, 2, 3, 4, 5, 6, 7, 8, 9>' requested here
        FooBuffer() : FooBuffer(std::make_index_sequence<BufferSize>{}) {}
                      ^
prog.cc:32:16: note: in instantiation of member function 'FooBuffer<10>::FooBuffer' requested here
        FooBuffer<10> foo;
                      ^
/opt/wandbox/clang-head/include/c++/v1/array:143:9: note: copy constructor of 'array<Foo, 10>' is implicitly deleted because field '__elems_' has a deleted copy constructor
    _Tp __elems_[_Size];
        ^
prog.cc:8:2: note: 'Foo' has been explicitly marked deleted here
        Foo(const Foo& rhs) = delete;   
        ^
1 error generated.

这是编译器之间在保证复制省略的实现上的分歧吗?或者,我在这里看到了这样的指示,即保证复制省略是不能依赖的,对编译器来说是完全可选的。这适用于这里吗,还是只适用于有复制构造函数且正确代码不需要GCE的情况?

共有1个答案

艾晋
2023-03-14

当你这么做的时候

_buffer({{(static_cast<void>(Is), Foo{})...}})

{(static_cast (Is),Foo{})...} 部分为对象构建一个braced-init-list。外部{}是用于创建braced-init-list引用的对象的大括号。由于这些列表中没有一个类型,编译器必须枚举_buffer的构造函数以找出要调用什么。当编译器执行此操作时,所有找到的都是隐式生成的copy和move构造函数。由于foo不是可复制/移动的,因此它们被隐式删除,这意味着没有可以调用的构造函数

如果切换到

_buffer{(static_cast<void>(Is), Foo{})...}
_buffer(std::array<Foo,BufferSize>{{(static_cast<void>(Is), Foo{})...}})

相关的标准语言可以在[dcl.init]/17中找到

  • 如果初始值设定项表达式是prvalue,并且源类型的CV非限定版本与目标的类是相同的类,则使用初始值设定项表达式初始化目标对象。

强调我的

 类似资料:
  • 我正在LWJGL中处理一个项目,OpenGL设置适用于2.0,但每当我尝试在LWJGL 3.0上渲染时,它都会返回。 返回此错误的方法:

  • 显然,json 架构不喜欢这个正则表达式: https://regex101.com/r/qsyUoQ/1 我收到一个错误:。此错误意味着我使用的正则表达式模式根据json模式无效。 我的正则表达式似乎对大多数其他解析器都有效。json模式支持正面和负面的前瞻性和捕获组:https://json-schema.org/understanding-json-schema/reference/regu

  • 谁能解释一下我如何用presto编写这个查询?我发现另一篇文章似乎暗示它的工作正确,所以我有点困惑。

  • 假设我们有以下简单的代码: 这段代码使用clang编译并打印“T”,但使用gcc我们有以下错误: 我的问题是哪个编译器有bug,gcc还是叮当声?

  • 在这个问题中,确认了< code > _ _ builtin _ CPU _ supports(" av x2 ")不检查操作系统支持。从英特尔文档中,我知道除了检查CPUID位之外,我们还需要检查与x86-64指令< code>xgetbv相关的内容。上面链接的英特尔文档提供了用于检查的代码: 问题:这个检查加上CPUID检查是否足以保证AVX2指令不会使我的程序崩溃? 额外问题:这张支票到底在

  • 在函数式编程语言中,对集合最原始/基本的操作是同态;它(大致)是