草庐IT

c++ - 显式默认的 constexpr ctor 是否应该允许非 constexpr 初始化

coder 2024-02-17 原文

我只是偶然发现了 GCC 和 Clang 之间关于显式默认的 constexpr ctor 和一些继承的以下差异......

template <typename T>
struct A {
  constexpr A() = default;
  T v;
};

struct B : A<int> {
  constexpr B() = default;
};

GCC 立即拒绝该代码,而 Clang 允许实例化这两种类型的非 constexpr 版本。我的猜测是 Clang 可能是正确的,但我不能 100% 确定...

最佳答案

问题归结为: 是默认初始化的 constexpr 构造函数 一些内置类型有效的非静态数据成员, 如果不使用呢?


tl;dr:

  • 对于非模板构造函数, 不,保留任何未初始化的非静态数据成员是无效的。

  • 对于模板构造函数,是的, 有一些(但不是全部,不需要诊断)是有效的 实例化模板特化 实例化的构造函数不满足要求 一个 constexpr 构造函数。

在这种情况下,GCC 是正确的,而 Clang 是错误的。


GCC 给出了以下非常有用的错误消息:

prog.cc:8:13: error: explicitly defaulted function 'constexpr B::B()' cannot be declared as 'constexpr' because the implicit declaration is not 'constexpr':
    8 |   constexpr B() = default;
      |             ^
prog.cc:3:13: note: defaulted constructor calls non-'constexpr' 'A<T>::A() [with T = int]'
    3 |   constexpr A() = default;
      |             ^
prog.cc:3:13: note: 'A<T>::A() [with T = int]' is not usable as a 'constexpr' function because:
prog.cc:4:5: note: defaulted default constructor does not initialize 'int A<int>::v'
    4 |   T v;
      |     ^

live demo

请注意,错误是在 B 的构造函数上引发的, 而不是 A , 其构造函数仅仅是“不能用作 constexpr 函数 因为 [the] 默认的默认构造函数 不初始化 int A<int>::v


根据 [dcl.constexpr]/4 :

The definition of a constexpr constructor shall satisfy the following requirements:

  • the class shall not have any virtual base classes;
  • each of the parameter types shall be a literal type.

In addition, either its function-body shall be = delete, or it shall satisfy the following requirements:

  • [...]
  • every non-variant non-static data member and base class subobject shall be initialized ([class.base.init]);
  • [...]

在这里,v类型为 int , 并且没有被初始化。 因此,似乎 A 的构造函数 不能申报constexpr .

然而,[dcl.constructor]/6说:

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression. If no specialization of the template would satisfy the requirements for a constexpr function or constexpr constructor when considered as a non-template function or constructor, the template is ill-formed, no diagnostic required.

因此,A 的构造函数即声明constexpr 实际上是有效的, 即使为 T = int 实例化!


问题是 B 的构造函数. B是一个普通类(与类模板相对), 并为其构造函数(仅)声明 constexpr , A<int>必须有一个 constexpr构造函数, 事实并非如此。

因此,应该像 GCC 一样拒绝此代码。


(请注意,两个编译器都拒绝对此类类型进行初始化, 例如:

A a{};
B b{};

以上代码被两个编译器拒绝。)

comment 中所述, 初始化 A::v GCC(和标准)会很高兴。

关于c++ - 显式默认的 constexpr ctor 是否应该允许非 constexpr 初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56085013/

有关c++ - 显式默认的 constexpr ctor 是否应该允许非 constexpr 初始化的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  7. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  8. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  9. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  10. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

随机推荐