如果实例化,如何使模板化变量专用化在编译时失败
How can I make a templated variable specialization fail at compile time if instantiated?
当且仅当模板化变量的默认专用化被实例化时,是否有可能出现编译时错误?例如
template<typename T>
constexpr int foo = /* Something that fails */;
template<>
constexpr int foo<bool> = 42;
// ...
int bar = foo<bool>; // All good!
int meow = foo<int>; // Error if and only if this line exists
我尝试输入的所有/* Something that fails*/
最终都失败了,即使没有实例化专业化。这可能吗?如果可以通过像static_assert
这样的机制以某种方式报告错误,以便至少在某种程度上清晰易读,那就更好了。
如果这是标准的,您应该询问语言律师。Clang 不会让你将模板化的 constexpr 变量保留为未定义,但它会让你从 constexpr 初始值设定项引用未定义的模板实例化。然后你可以这样写:
template<typename T>
struct no_such_type_for_foo;
template<typename T>
constexpr int foo = no_such_type_for_foo<T>::value;
template<>
constexpr int foo<int> = 4;
int main()
{
int y = foo<int>; // all good
int z = foo<bool>; // implicit instantiation of undefined template 'no_such_type_for_foo<bool>'
}
gcc
不喜欢模板实例化中的static
关键字。
但是,仅未定义默认模板似乎就可以解决问题:
template<typename T>
constexpr int foo;
template<>
constexpr int foo<bool> = 42;
有了这个,这就可以了:
std::cout << foo<bool> << std::endl;
这失败了:
std::cout << foo<char> << std::endl;
跟:
t.C:2:15: error: uninitialized const ‘foo<char>’ [-fpermissive]
constexpr int foo;
^
我认为这种情况与未定义默认模板的更常见情况之间没有太大区别:
template<typename T> class foo;
template<>
class foo<char> {
// ...
};
同样的事情。
基于 zneak 和 Sam 的解决方案,我想出了一个允许通过 static_assert
自定义错误消息的变体。关键是static_assert
条件需要依赖于模板参数,否则无论是否实际使用模板,都会立即进行评估。
问题是我们希望static_assert
无条件失败,因此对于每个可能的参数,条件应该减少到false
。我们依赖于编译器本身不进行分析(我不确定如果模板没有实例化,它是否真的会被允许弄清楚)。
template<typename T>
constexpr int no_such_type_for_foo()
{
static_assert(sizeof(T) < 0, "No such type for foo");
return 0;
}
template<typename T>
constexpr int foo = no_such_type_for_foo<T>();
template<>
constexpr int foo<bool> = 42;
int main()
{
int y = foo<bool>; // all good
int z = foo<int>; // static_assert failed "No such type for foo"
}
相关文章:
- 编译时检查特征专用化是否具有唯一 ID
- DLLexport 类模板实例(专用化),减少了仅标头模板库的编译时间
- C++模板 - 使用"std::is_same_v"而不是专用并避免编译错误?
- 非命名空间范围内的显式专用化不会在 GCC 中编译
- 模板部分专用化和多个编译单元
- 一种安全、符合标准的方法,使类模板专用化仅在实例化时才无法使用"static_assert"进行编译
- 是否允许在模板专用化时从int转换为long(应该编译此代码)
- 成员模板专用化不使用 clang 进行编译
- 为非专用模板实例化强制执行编译错误
- C++模板专用化:编译错误:"is not a type"
- 使用g++编译时静态函数的模板专用化
- 模板专用化、默认参数和 VS2013 的编译错误
- 如果实例化,如何使模板化变量专用化在编译时失败
- 编译时的质因数列表:专用化错误
- 编译时的类型专用化
- 模板函数专用化不明确编译错误
- 编译错误:2574:<entity>必须在首次使用 () 之前显式专用化<entity>
- boost bind.hpp 1.54 c++ 专用模板无法在 Solaris 上编译。有效C++?
- 基于编译时值的 C++ 模板专用化
- 在模板专用化中强制出现编译时错误