Clang 错误:调用私有构造函数,而实际上没有调用它们

Clang error: calling a private constructor while none of them were actually called

提问人:Ya Ihniy 提问时间:6/18/2023 最后编辑:Peter MortensenYa Ihniy 更新时间:6/18/2023 访问量:150

问:

我做了一个类的静态函数,并将构造函数设为私有。现在我想使用这个函数。Clang++ 说“构造函数是私有的”,而 g++ 可以正常编译。

我不知道任何标准中是否有任何规则可能会以任何方式影响这一点。任何函数都可以生成一个变量,并且没有变量,并且无法返回值。所以上面的代码中应该没有任何错误,对吧?但 Clang 对此有不同的看法。MyStruct::make

这是 Clang 应该做到的,还是永远不应该在 C++ 中做的事情?

我试图让 C++ 在这里更像 Rust,这样我就永远不会对构造函数做一些意想不到的事情。我使用了 g+,以下代码有效。

#include <iostream>
#include <optional>
#include <utility>

class MyStruct {
public:
  static auto make(int val) -> MyStruct {
    MyStruct that(val);
    return that;
  };

  auto copy() -> MyStruct {
    MyStruct copy(this->val);
    return copy;
  }

  auto value() -> int { return this->val; }

private:
  MyStruct() = delete;

  MyStruct(int val) { this->val = val; }

  MyStruct(const MyStruct &other) { this->val = other.val; }

  int val;
};

auto main() -> int {
  auto my_struct = MyStruct::make(4);

  auto my_new_struct = my_struct.copy();

  std::cout << my_new_struct.value();
  std::cout << MyStruct::make(7).value();
}

但是,使用 Clang 时,我遇到了一些错误:

main.cpp:30:20: error: calling a private constructor of class 'MyStruct'
  auto my_struct = MyStruct::make(4);
                   ^
main.cpp:24:3: note: declared private here
  MyStruct(const MyStruct &other) { this->val = other.val; }
  ^
main.cpp:32:24: error: calling a private constructor of class 'MyStruct'
  auto my_new_struct = my_struct.copy();
                       ^
main.cpp:24:3: note: declared private here
  MyStruct(const MyStruct &other) { this->val = other.val; }
  ^
2 errors generated.

换句话说,这是 Clang 应该做到的,还是永远不应该在 C++ 中做的事情,为什么?

C clang 构造函数 clang++ 复制省略

评论


答:

0赞 cse 6/18/2023 #1

这取决于您的编译器版本和编译器标志。

对于 Clang 版本 5.0.1,代码使用 C++17(编译器开关 -std=c++17)进行编译,但不在 C++11(编译器开关 -std=c++11)上编译。

请参阅此处的代码是使用 set 编译的。但是如果我们将 .-std=c++17-std=c++11

1赞 Vlad from Moscow 6/18/2023 #2

形式上,例如在这一行中

auto my_struct = MyStruct::make(4);

如果不考虑复制/移动省略,则应使用复制结构器。

在 C++ 17 标准之前,复制构造函数应该是可以接受的,即使它的调用被省略了。

来自 C++ 14 标准( 12.8 复制和移动类对象)

  1. ...[注意:无论是否会发生复制省略,都必须执行此两阶段过载解决。它决定了 未执行省略时调用的构造函数,以及 即使省略了调用,选定的构造函数也必须可访问。 — 结束语 ]

要么公开复制构造函数,要么打开至少对 C++ 17 标准的支持。

评论

0赞 Ya Ihniy 6/18/2023
这真是太神奇了。这很有道理,但非常令人惊讶。奇怪的是,我没有想到移动语义之前不在 C++ 中。谢谢。
0赞 Vlad from Moscow 6/18/2023
@YaIhniy完全没有。不客气:)