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