如何在编译时如果实例化模板变量专业化失败?

问题描述:

当且仅当模板变量的默认特化被实例化时,是否有可能获得编译时错误?例如如何在编译时如果实例化模板变量专业化失败?

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这样的机制以某种方式报告错误,那么它至少有点清晰。

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> { 

// ... 
}; 

同样的事情。

+1

不幸的是,clang并没有如此放纵:'错误:const类型'const int'对象的默认初始化(即使没有在任何地方引用)。 – Trillian

+0

如何:template constexpr int foo = std :: enable_if :: value> :: type(); –

基于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" 
}