草庐IT

c++ - 具有模板特化的 constexpr 数组成员 : inconsistent behavior cross compilers

coder 2024-02-05 原文

考虑以下代码:

#include <iostream>

template<class T>
struct foo {};

template<>
struct foo<int> {
  static constexpr char value[] = "abcde";
};

template<class T>
struct bar {
  static constexpr char value[] = "abcde";
};

template<class T>
struct baz {
  static constexpr int value = 12345;
};

int main() {
    char c = foo<int>::value[2];
    char d = bar<int>::value[2];
    int e = baz<int>::value;

    std::cout << c << d << e << "\n";
    
}

编译时:clang++ -std=c++14 ./test_foo.cc ,我收到 undefined symbol 的链接器错误:bar<int>::valuefoo<int>::value .当我更改为 clang++ -std=c++17 ,那么只有一个 undefined symbol :foo<int>::value .我的 clang++ 版本是 5.0。

然而,当我尝试 g++ -std=c++14 ./test_foo.cc ,编译成功。我的 g++ 版本是 5.4.0。

我有两件事要问。

1) 从 C++ 标准的角度来看,哪个编译器的行为正确?

我用谷歌搜索并阅读了许多 cppreference 页面,但没有发现任何与这种现象真正相关的内容。特别是对于带有 -std=c++17 的 clang++ ,行为真的很奇怪,因为bar<int>通过了但是foo<int>失败,唯一的区别是 foo<int>是一个专业。我从http://en.cppreference.com/w/cpp/language/constexpr读到那个

A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline.

因此似乎没有理由进行模板特化foo<int>失败。此外,我在链接之前查看了生成的目标文件,访问 foo<int>::value[2]; 没有像人们期望的那样在编译时完成。我高度怀疑 clang++ 编译器有问题。

2) 如何处理这个 clang++ 链接错误?

我试过类似 Undefined reference to static constexpr char[] 的东西, 但最后我找不到任何方法来克服这个链接错误。所以我只是想知道是否有办法让这个链接成功。

最佳答案

直到 C++17,原因与 the question you found 中所述完全相同(我认为 Shafik Yaghmour 发布的答案更准确地解释了这个问题)。简而言之,定义一个constexpr如果成员是 odr-used,静态数据成员仍然是必需的.

您可以 resolve the problem通过提供这些变量的定义直到 C++17(即使用 -std=c++14)。


自 C++17 起,当前标准在 [dcl.constexpr] paragraph 1 中说

... A function or static data member declared with the constexpr specifier is implicitly an inline function or variable ([dcl.inline]).

[basic.def] paragraph 2 中说

A declaration is a definition unless

  • ...

  • it declares a non-inline static data member in a class definition ([class.mem], [class.static]),

  • ...

因此不需要命名空间范围内的此类定义。

此外,现行标准在[depr.static_constexpr] paragraph 1

For compatibility with prior C++ International Standards, a constexpr static data member may be redundantly redeclared outside the class with no initializer. This usage is deprecated. [ Example:

struct A {
  static constexpr int n = 5;  // definition (declaration in C++ 2014)
};

constexpr int A::n;  // redundant declaration (definition in C++ 2014)

— end example ]

所以你最好从 C++17 开始避免这样的定义。

When I change to clang++ -std=c++17, then only one undefined symbol: foo<int>::value.

这是一个 Clang 错误。不管怎样,它works well适用于 Clang HEAD 7.0.0。

关于c++ - 具有模板特化的 constexpr 数组成员 : inconsistent behavior cross compilers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48361845/

有关c++ - 具有模板特化的 constexpr 数组成员 : inconsistent behavior cross compilers的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

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

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

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  5. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

  8. ruby - Chef Ruby 遍历 .erb 模板文件中的属性 - 2

    所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

随机推荐