【问题标题】:Different behavior observed with constexpr auto/char-array variable使用 constexpr auto/char-array 变量观察到不同的行为
【发布时间】:2016-01-14 15:31:17
【问题描述】:

跟进这个问题Having a constexpr static string gives a linker error

在问题中,此代码无法编译:

#include <iostream>

struct Test { static constexpr char text[] = "Text"; };

int main()
{
    std::cout << Test::text << std::endl; // error: undefined reference to `Test::text'
}

从评论来看,这段代码可以编译:

#include <iostream>

struct Test { static constexpr auto text = "Text"; };

int main()
{
    std::cout << Test::text << std::endl;
}

我的问题是为什么auto 版本可以工作,而char 版本的数组却不行?

您能否指出标准中允许第二个版本和不允许第一个版本的声明?

我看了Strange behavior with constexpr static member variable,但似乎是另一个问题。

【问题讨论】:

  • 这是同一个问题,同样接受的答案是有效的:stackoverflow.com/a/28534978/113662 即两个版本都是错误的,但编译器没有义务拒绝它们,它选择接受其中一个
  • @TadeuszKopec 不,后者不是病态的。
  • @TadeuszKopec 我错过了 Sahu 的答案,这是对已接受答案的补充。在萨胡的回答中,提到了文字类型。而且,我误解了,文本将被推导出 char[] 而不是 char*
  • @Columbo 你是对的,这里提到的例外情况。

标签: c++ c++11 language-lawyer constexpr auto


【解决方案1】:

类中静态数据成员的声明绝不是定义。
您的示例之间的区别在于,只有一个需要定义 text

auto 版本推导出char const*,因此text 仅适用于左值到右值的转换,而不是 odr 使用的。相比之下,第一个代码有效地传递了text 的地址,odr-use-ing 它 - 即需要定义。

【讨论】:

  • 是的,关键是text推导出char const*而不是char[]。我误解了这一点。
  • const char* 不是地址吗?我很困惑。
  • @Lingxi 没有,const char* 是指针类型。不过,传递给对应operator&lt;&lt;重载的这个指针类型的对象代表text中第一个char的地址。
  • 哦,我明白了。在第二个版本中,没有取址操作。在第一个版本中,数组到指针的转换涉及地址获取,因此是 ODR 使用的。
  • @Lingxi 嗯,也有例外。例如,写 std::cout &lt;&lt; Test::text[0]; 不是 odr 使用,尽管 text 的地址是隐含的。但是,总的来说,这是正确的。-
【解决方案2】:
struct Test { static constexpr auto text = "Text"; };

解析为

struct Test { static constexpr const char * text = "Text"; };

所以第二个表达式是指针的constexpr 值而不是数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2017-05-06
    • 2023-03-25
    • 1970-01-01
    • 2021-10-17
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多