匿名命名空间中的constexpr字符串文字
constexpr string literals in anonymous namespace?
我有下面的示例代码,它使用字符串文字作为模板参数,这样基类模板就可以访问字符串。
代码编译了,但我收到了一个我不完全理解的警告:
警告:"ns::bar::type"有一个基"ns::base<((const char*)(&ns::bar::name)>'其类型使用匿名命名空间[由启用默认值]
下面的工作示例代码:
// "test.h"
#pragma once
namespace ns
{
template <char const* str>
struct base
{
const char *name() const { return str; }
};
namespace bar
{
static constexpr char name[] = "bar";
struct type : base<name> {}; // <-- this line here
}
}
// main.cpp
#include <iostream>
#include "test.h"
int main()
{
ns::bar::type f;
std::cout << f.name() << std::endl;
return 0;
}
所以我的问题是:
- 这个警告是什么意思
- 以我在这里所做的方式将字符串文本作为模板参数传递是否安全
(注意这与gcc 4.7.2有关)
问题与static constexpr char name[] = "bar";
具有内部链接这一事实有关。
在标头中定义了内部链接的任何类型在包含标头的每个文件中都将是不同的类型
这很少是故意的,因此发出了警告。
在源文件中执行此操作时没有警告的原因是,该类型永远不能被多个文件引用,因此它将始终是一个类型。
警告是因为name
在包含test.h
的每个源文件中都有不同的地址。因为它有内部链接(static
),所以每个翻译单元都会得到自己的副本;它们将不会被链接器统一。这意味着你的代码相当于:
template<int> struct base { ... };
static constexpr int val = some_value_different_in_every_source_file;
struct type: base<val> {};
您的代码是合法的,但如果您在另一个源文件中包含test.h
,则它将违反一个定义规则:
3.2一个定义规则【basic.def.odr】
[…]
6-可以有不止一个类类型的定义[…]提供[…]:[…]
- 在
D
的每个定义中,相应的名称[…]可以引用一个常量对象如果[…]使用了对象的值(但不是地址)[…],则具有内部链接或无链接[仅]
在类类型的定义中,您使用的是具有内部链接的对象的地址,因此在多个转换单元中使用它是未定义的行为。
相关文章:
- 是否可以将带有字符串化运算符的宏转换为 constexpr?
- 将字符串存储在 constexpr 结构中
- 生成 constexpr 字符串表,不能产生常量表达式
- 为什么必须将 const 添加到 constexpr 中才能进行字符串文字声明?
- C++17 constexpr字符串解析
- C++17 在逗号上拆分 constexpr 字符串并在编译时有元素的数量?
- 通过 constexpr 中的 'const char *' glvalue 访问字符串文字的值会出错
- 列出<Char>C++中键入的 constexpr 字符串
- 使用 constexpr 初始化非常量静态字符串
- VS15使用constexpr和字符串文字引发错误C2975
- 警告:ISO C++禁止将静态“constexpr char*”数据成员的字符串常量转换为“char*”
- 如何在 constexpr 函数内的字符串文字上静态断言条件
- 对静态 constexpr 字符串的未定义引用(除非它是一个指针)
- constexpr,用于连接两个或多个字符字符串
- C++11 通过 constexpr 在编译时获取字符串长度
- C++11 constexpr 字符串实现
- 使用 constexpr 编译时间字符串串联
- 在编译时计算C字符串的长度.这真的是constexpr吗
- 带字符串操作变通方法的constexpr
- 匿名命名空间中的constexpr字符串文字