C++ 静态断言与SFINAE
考虑这一点:C++ 静态断言与SFINAE,c++,c++11,sfinae,static-assert,C++,C++11,Sfinae,Static Assert,考虑这一点: template <typename T> struct hash { static_assert(false,"Not implemented."); }; struct unhashable {}; template <typename T> auto test(const T &t) -> decltype((*(hash<T> const *)nullptr)(t),int); void test(...);
template <typename T>
struct hash
{
static_assert(false,"Not implemented.");
};
struct unhashable {};
template <typename T>
auto test(const T &t) -> decltype((*(hash<T> const *)nullptr)(t),int);
void test(...);
int main()
{
std::cout << std::is_same<decltype(test(std::declval<unhashable>())),void>::value;
}
模板
结构散列
{
静态_断言(false,“未实现”);
};
结构不可破坏{};
模板
自动测试(常量T&T)->decltype((*(哈希常量*)nullptr)(T),int);
孔隙试验(…);
int main()
{
标准::cout
在GCC4.7上,编译失败。我非常肯定这将在GCC4.8中编译正常(但目前无法检查)。谁是对的
静态断言中的条件不依赖于任何模板参数。因此,编译器可以在解析模板时立即将其求值为false
,并意识到应该触发断言-无论您是否在其他地方实际实例化模板
在任何编译器上都应该如此。在任何兼容的编译器中编译都必须失败
SFINAE规则基于声明而非定义。(如果我在这里使用了错误的术语,很抱歉。)我的意思是:
对于类/结构:
template < /* substitution failures here are not errors */ >
struct my_struct {
// Substitution failures here are errors.
};
那就试试这个
template <typename T>
typename enable_if<std::is_integral<T>::value, int>::type
test(const T &t);
void test(...);
int main()
{
std::cout << std::is_same<decltype(test(0)), int>::value << std::endl; // OK
std::cout << std::is_same<decltype(test(0.0)), void>::value << std::endl; // Error: No SFINAE Here
}
可能是Fair enough的重复,我将在一段时间内检查GCC4.8上到底发生了什么。我想根本的问题是,静态_assert()是否算作“替换失败”还是更严重的问题?@Bluescani:这不是替换失败,而是一个硬错误,因为它不会发生在函数类型及其模板参数的types@Andy.我相信,static\u assert
中的条件不依赖于T
这一事实没有任何区别看看我的答案,可以随意改进。@Cassio:不确定我是否误解了,但是当条件取决于模板参数时(例如,static\u assert(std::is\u算术::value,“!”
),编译器将仅在模板实际实例化时对其进行计算,并且只要t
是算术类型,编译器就不会停止编译。但是,即使模板从未实例化,并且如果其计算结果为false
,编译器也将对不依赖于t
的条件进行计算(与本例一样),编译在任何情况下都将停止。也就是说,我同意您的观点,即不应将static\u assert()
用于SFINAE@Andy.确切地说,这就是我的意思:static\u assert
不能用于SFINAE。我同意你的观点,评估的时间取决于它是否依赖于类型。
// Primary template (OK)
template <bool, typename T>
struct enable_if;
// Specialization for true (also OK)
template <typename T>
struct enable_if<true, T> {
using type = T;
};
// Specialization for false (Wrong!)
template <typename T>
struct enable_if<false, T> {
static_assert(std::is_same<T, T*>::value, "No SFINAE here");
// The condition is always false.
// Notice also that the condition depends on T but it doesn't make any difference.
};
template <typename T>
typename enable_if<std::is_integral<T>::value, int>::type
test(const T &t);
void test(...);
int main()
{
std::cout << std::is_same<decltype(test(0)), int>::value << std::endl; // OK
std::cout << std::is_same<decltype(test(0.0)), void>::value << std::endl; // Error: No SFINAE Here
}
1
1