本文介绍了静态断言和SFINAE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下问题:

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;
}

除了明显缺少的标头之外,应该编译吗?

Apart from obviously missing headers, should this compile?

换句话说,我要问的是,是否要求在尾随的decltype内触发静态断言失败,同时推断出重载的函数模板的返回值,以要求中止编译,或者是否需要将重载简单地

In other words, I am asking if the static assertion failure triggering inside a trailing decltype while deducing the return value of an overloaded function template is requested to halt the compilation, or if the overload has simply to be discarded.

在gcc 4.7上,编译失败。我非常肯定,尽管它可以在gcc 4.8中编译正常(但目前无法检查)。谁是正确的?

On gcc 4.7, compilation fails. I am pretty positive though that this will compile ok in gcc 4.8 (but cannot check at this very moment). Who is right?

推荐答案

在任何兼容的编译器中编译都将失败。

The compilation has to fail in any compliant compiler.

SFINAE规则基于声明而不是定义。 (很抱歉,如果我在这里使用了错误的术语。)我的意思是:

SFINAE rules are based on declarations and not definitions. (Sorry if I'm using the wrong terminology here.) What I mean is the following:

对于类/结构:

template < /* substitution failures here are not errors */ >
struct my_struct {
    // Substitution failures here are errors.
};

对于功能:

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 */
}

此外,对于给定的模板参数集,不存在结构/函数

In addition, the non existence of the struct/function for the given set of template arguments is also subject to SFINAE rules.

现在, static_assert 只能出现在替换失败是错误的区域,因此,如果触发,则会出现编译器错误。

Now a static_assert can only appear in the regions where substitution failures are errors and, therefore, if it fires, you'll get a compiler error.

例如,以下是 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.
};

然后尝试一下

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
}

如果删除了 enable_if false ,然后代码编译并输出

If you remove the specialization of enable_if for false then the code compiles and outputs

1
1

这篇关于静态断言和SFINAE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 12:44