在 GCC 和 Clang 中,我们可以将整数变量传递给属性。
constexpr auto SIZE = 16;
int a [[gnu::vector_size(SIZE)]];
Run Code Online (Sandbox Code Playgroud)
当我们编写模板时,这特别有用。
template<size_t N>
struct Vec {
int inner [[gnu::vector_size(N)]];
};
Run Code Online (Sandbox Code Playgroud)
但是,如果该属性需要一个字符串,我找不到使用这样的变量的方法。这两种方法都不起作用。
constexpr const char* TARGET = "default";
[[gnu::target(TARGET)]] void foo() {}
Run Code Online (Sandbox Code Playgroud)
constexpr const char TARGET[] = "default";
[[gnu::target(TARGET)]] void foo() {}
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这一目标?
采用字符串的标准属性(例如[[depecrated("reason")]])采用字符串文字,而不是变量或其他表达式。这就像声明中的消息static_assert。
查看 gcc 样式__attribute__说明符的 gcc 文档https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax:
可能为空的以逗号分隔的表达式列表。例如,
format_arg属性使用此形式,列表是单个整数常量表达式,alias属性使用此形式,列表是单个字符串常量。
其中SIZE将是整数常量表达式,但“字符串常量”似乎意味着字符串文字而不是类型const char[N]或的常量表达式const char*。C++ 形式可能[[attribute]]也需要字符串常量/文字,就像标准属性一样。
您可以使用宏来做到这一点:
#define TARGET "default"
[[gnu::target(TARGET)]] void foo() {}
Run Code Online (Sandbox Code Playgroud)
或者您可以使用以下命令对整个代码区域执行此操作_Pragma("GCC target default"):
#pragma GCC push_options
#pragma GCC target "default"
void foo() {}
#pragma GCC pop_options
Run Code Online (Sandbox Code Playgroud)
...除了这似乎是 GCC 的 bug,其中编译器的某些部分无法识别target("default")。而且这个编译指示通常在 C++ 中似乎不起作用(在一些简单的测试中使用 Clang 或 GCC),所以这可能不起作用。不过,它可能会在未来得到修复。
不管怎样,这些都不适用于模板。似乎没有技术原因说明const char*类型表达式不应该被允许,只是似乎没有人实现它并且它还没有标准化。