blu*_*rni 10 c++ static-assert sfinae c++11
考虑一下:
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;
}
Run Code Online (Sandbox Code Playgroud)
除了显然缺少标题,这应该编译吗?
换句话说,我问的是,如果在推断重载函数模板的返回值的同时触发尾随decltype内部的静态断言失败是否要求停止编译,或者是否只是丢弃了重载.
在gcc 4.7上,编译失败.我很积极,虽然这将在gcc 4.8中编译好(但在此刻无法检查).谁是对的?
Cas*_*eri 15
编译必须在任何兼容的编译器中失败.
SFINAE规则基于声明而非定义.(对不起,如果我在这里使用了错误的术语.)我的意思是:
对于类/结构:
template < /* substitution failures here are not errors */ >
struct my_struct {
// Substitution failures here are errors.
};
Run Code Online (Sandbox Code Playgroud)
对于功能:
template </* substitution failures here are not errors */>
/* substitution failures here are not errors */
my_function( /* substitution failures here are not errors */) {
/* substitution failures here are errors */
}
Run Code Online (Sandbox Code Playgroud)
此外,给定模板参数集的结构/函数的不存在也受SFINAE规则的约束.
现在static_assert
只能出现在替换失败错误的区域,因此,如果它触发,您将收到编译器错误.
例如,以下是错误的实现enable_if
:
// 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.
};
Run Code Online (Sandbox Code Playgroud)
然后尝试这个
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
}
Run Code Online (Sandbox Code Playgroud)
如果删除enable_if
for的特化,false
则代码编译并输出
1
1
Run Code Online (Sandbox Code Playgroud)
在gcc 4.7上,编译失败.我很积极,虽然这将在gcc 4.8中编译好(但在此刻无法检查).谁是对的?
静态断言中的条件不依赖于任何模板参数.因此,编译器可以false
在解析模板时立即对其进行评估,并意识到断言应该触发 - 无论您是否实际在其他地方实例化模板.
任何编译器都应该如此.