任何使用用户定义的构造函数具有隐式寿命类型的方法?

问题描述 投票:0回答:0
Tldr;

我们可以将不可仿制的,不可移动的类制成零默认初始化为隐式寿命类型而不更改现有构造函数吗?


直接从C ++ 23规格中直接

9 A class S is an implicit-lifetime class if (9.1) — it is an aggregate whose destructor is not user-provided or (9.2) — it has at least one trivial eligible constructor and a trivial, non-deleted destructor.
但是“至少一个”是什么意思?  听起来像是许多可能的构造函数中的任何一个。  但是,规格还说,要使构造函数变得微不足道,必须是...

Implicitly declared or explicitly defaulted (= default) on its first declaration.
由于只有特殊的成员功能才能是其中的,因此只有特殊的成员功能在技术上才能微不足道。因此,答案在我看来:不是机会。

但我不是棚子里最锋利的工具,也可能缺少标准中的东西。

考虑这一最小化的类别。

template <typename T> struct Foo { T t; Foo() : t() { } Foo(Foo const &) = delete; Foo(Foo &&) = delete; }; static_assert(not std::is_trivially_default_constructible_v<Foo<int>>); static_assert(not std::is_trivially_copy_constructible_v<Foo<int>>); static_assert(not std::is_trivially_move_constructible_v<Foo<int>>);

但我们希望能够在需要它是隐式寿命类型的情况下使用这种类型的实例(何时可以以这种方式使用T)。 它目前不是隐式寿命类型。

,我们添加此。
template <typename T>
struct Foo
{
    // ...
    Foo(tag_t) { } // Kneel, bow, and pray...
};
有效地,

Foo<int>::foo(tag_t)

表现为微不足道的构造函数(对于

Foo() {}

)。
技术,
Foo<int>::Foo(tag_t)

不是一个琐碎的构造函数(对于

Foo() {} 
)。
FURTHERMORE,
P2674

中的参考实现仅检查默认/复制/移动构造函数是否琐碎。 我明白了,因为其他任何事情都需要编译器支持。 但是,标准本身说的是

构建器,编译器可以看到该构造函数什么都不做,因此它可以检测到有一个有效的琐碎构造函数...而且我在跨过手指和脚趾。
我猜想并非如此,但是截至今天,没有任何主要供应商的官方版本提供此类特征。
,鉴于默认/复制/移动构造函数并非微不足道 - 如何将
std::is_implicit_lifetime
变成隐式寿命类型 - 而不会更改当前默认/复制/移动构造函数 - 它将破坏使用这些类型的任何当前代码?

在您告诉我不要写这样的课程之前,这不是我的课程之一。  是的,是的,是给朋友的。  看,在标准库中至少有一个。  一种被视为在许多现有代码中的隐性寿命类型。  但是,从技术上讲,这不是,我正在尝试将其制作而不必写论文。
eDit 我试图在这里不涉及有关特定类型的问题,而是要将其遵守标准,以查看是否有解决此问题的方法。 但是,想帮助以不同方式提出同样问题的善良人士,所以这几乎就像我能保留的那样短)。 C ++ 20,Foo

被修改以通过其默认构造函数强制实施零限制。尽管此更改在大多数用例中都提高了安全性,但它通过删除其琐碎的默认构造函数和隐式寿命特征而无意中使不适合共享内存方案。

在共享内存中使用

std::atomic

现在导致不确定的行为。

std::atomic
提供解决方法,但它牺牲了封装和类型的安全性。该标准目前没有在共享内存中明确设计的针对原子操作的类型,尽管在其无锁操作规范中承认了此用例。

Imo,这是当时的监督。 该论文
P0883

试图确保初始化的

std::atomic<int>
为零。是的,这看起来很奇怪 - 如果您需要更多详细信息,请阅读论文。 不过,它远远超出了所有

std::atomic_ref类型的默认初始化零初始化而不是默认初始化。 因此,自开始时,

std::atomic<int> i{}

的复制/移动构造函数已被删除,这是有充分理由的。 使用C ++ 20,即使是

std::atomic

std::atomic
。 这是我的示例的确切情况。 我认为无论是在谈论我的
T
还是

int

,然后将其带入其中并不重要,只是使讨论变得更加复杂。

	
标准没有任何共享内存的概念(除了观察到某些并发基础的实现可以通过避免基于地址的表来支持这种情况)。  因此,没有办法说出我们真正想要的内容,也就不能说第二个过程可以从第一个过程创建的对象的值表示开头的新对象(这会……与原始过程有所不同一旦修改了吗?)但是第二个过程只需使用
same

对象。

如果我们确实有这样的概念,它将消除对隐式少数状态的需求,因为可以以第一个过程(在第一个过程中)开始使用寿命,并且该类型可以具有任何理想的不变性。 因此,我们不想为了用例外情况而削弱内隐千年的要求(从而损害不变的),而这种情况只会以两种不同的方式从中获利。

c++ c++20 c++23
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.