构造一个没有默认构造函数的空对象

Jus*_*tin 3 c++ language-lawyer empty-class c++17

假设我有一个类型F。我知道这F是空的,但F没有默认构造函数,所以我不能F()用来构造它。有没有办法获得有效的类型对象F?我似乎记得有一次提到工会的神秘用法有这样一种方式。理想情况下,这将是constexpr友好的。


这很有用,因为无捕获 lambda 仅在 C++20 中获得了默认构造函数。在 C++17 中,如果我想“将 lambda 传递给模板”并在没有实例的情况下调用该 lambda,我需要能够从类型中重建它。

auto const f = [](int x) { return x; };
using F = decltype(f);

static_assert(std::is_empty_v<F>);
static_assert(!std::is_default_constructible_v<F>);

magically-construct-an-F(42);
Run Code Online (Sandbox Code Playgroud)

Lan*_*yer 6

对于自己的类型,你可以禁止复制或自身举动,构造一个对象:F f = f。这本身不会导致 UB,请参阅CWG363。然而,编译器提供的闭包类型并不是很清楚,即使你知道它是空的。

  • @NicolBolas `MyClass foo(foo);` 我想? (2认同)

Nic*_*las 5

F没有默认构造函数

如果是这种情况,那么用户要么显式删除它,要么隐式删除它,因为用户提供了一些其他构造函数。无论哪种情况,类型都不是平凡的。

如果一个对象是非平凡的,那么要创建该类型的对象而不从现有实例复制/移动,您必须显式调用某种构造函数。这是无法回避的。

即使联合的常见初始序列规则也不允许您创建另一个对象。它只允许访问另一个对象的非静态数据成员。由于您的对象是空的,因此这对您来说没有任何价值。

  • @Justin:[这是intro.object/1](https://timsong-cpp.github.io/cppwp/intro.object#1)。它指定了对象存在的方式。隐式创建联合成员的规则不包括从函数返回指定成员。因此,那不是其中之一。因此,除非您能够显示标准在哪里明确指出这不是 UB,并且该代码以某种方式导致对象出现,否则所有这些编译器都会以这种方式被破坏。另外,如果您能找到这样的东西,请将其作为缺陷报告归档,因为您*不应该能够这样做*。 (2认同)