gpt4 book ai didi

C++ constexpr 继承构造函数

转载 作者:IT老高 更新时间:2023-10-28 23:18:37 26 4
gpt4 key购买 nike

以下代码可以使用 GCC 8.2 编译,但不能使用 Clang 6.0.1:

// A struct named Foo.
struct Foo
{
// Data member of type 'int'.
int val;

// Default constructor (constexpr).
constexpr Foo() noexcept : val(0) {}
};

// A struct named Bar.
struct Bar : Foo
{
// Make use of the constructors declared in Foo.
using Foo::Foo;

// A constructor taking an object of type Foo.
// COMMENTING THIS CONSTRUCTOR SOLVE THE COMPILATION ISSUE.
constexpr Bar(Foo const obj) noexcept : Foo(obj) {}
};


// A struct named Test.
struct Test
{
// Data member of type 'Bar'.
Bar bar;

// A defaulted default constructor.
constexpr Test() noexcept = default;
};


// Main function.
int main() { return 0; }

Clang 失败并显示以下消息:

error: defaulted definition of default constructor is not constexpr
constexpr Test() noexcept = default;

我想了解 Clang 拒绝此代码的原因。

最佳答案

看起来 clang 依赖于 C++14 部分 [class.inhctor]p3 中的 pre C++17 措辞:

For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the complete class where the using-declaration appears or the constructor would be a default, copy, or move constructor for that class. Similarly, for each constructor template in the candidate set of inherited constructors, a constructor template is implicitly declared with the same constructor characteristics unless there is an equivalent user-declared constructor template ([temp.over.link]) in the complete class where the using-declaration appears. [ Note: Default arguments are not inherited. An exception-specification is implied as specified in [except.spec]. — end note ]

所以在 C++14 中:

using Foo::Foo;

表示 Bar 不继承 Foo 的默认构造函数,并且 Bar 没有默认构造函数,因为它被您的声明所禁止:

constexpr Bar(Foo const obj) noexcept : Foo(obj) {}

Bar 添加默认构造函数可解决问题 see it live :

constexpr Bar() = default ;

论文 p0136r1: Rewording inheriting constructors (core issue 1941 et al) 在 C++17 中更改了措辞可以看到是从Changes between C++14 and C++17 DIS 接受的

The following papers were moved at committee meetings, but their contents are too specific to call out as separate features: N3922, N4089, N4258, N4261, N4268, N4277, N4285, P0017R1, P0031R0, P0033R1, P0074R0, P0136R1, P0250R3, P0270R3, P0283R2, P0296R2, P0418R2, P0503R0, P0509R1, P0513R0, P0516R0, P0517R0, P0558R1, P0599R1, P0607R0, P0612R0

我们可以看到 p0136r1 被移除了 [class.inhctor]:

Remove 12.9 class.inhctor, "Inheriting constructors".

我在 p0136r1 中看不到任何会限制这种情况的措辞。缺陷报告列表并未具体涵盖这种情况,但措辞变化似乎是一致的。

所以看起来 gcc 在这里是正确的,我们有一个潜在的 clang 错误。

gcc 7 发行说明

我们还在 gcc pre 7.x (see it live) 中获得诊断。如果我们查看 gcc 7 release notes我们看到:

The default semantics of inherited constructors has changed in all modes, following P0136. Essentially, overload resolution happens as if calling the inherited constructor directly, and the compiler fills in construction of the other bases and members as needed. Most uses should not need any changes. The old behavior can be restored with -fno-new-inheriting-ctors, or -fabi-version less than 11.

这似乎证实了最初的结论。如果我们将 -fno-new-inheriting-ctors 与您的程序稍作修改的版本一起使用 it no longer compiles P0136 改变了这一点。

关于C++ constexpr 继承构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51853091/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com