当一个人说SFINAE友好的时候是什么意思?

Meh*_*dad 23 c++ sfinae

当人们提到某个特定的函数,结构或者......对SFINAE友好时,我无法清楚地理解它意味着什么.

有人请解释一下吗?

Jar*_*d42 23

当它允许替换失败而没有硬错误(as static_assert).

例如

template <typename T>
void call_f(const T& t)
{
    t.f();
}
Run Code Online (Sandbox Code Playgroud)

该函数是为所有人声明的T,即使是那些没有的函数f,因此您无法进行SFINAE,call_f<WithoutF>因为该方法确实存在.(非编译代码的演示).

随着以下变化:

template <typename T>
auto call_f(const T& t) ->decltype(t.f(), void())
{
    t.f();
}
Run Code Online (Sandbox Code Playgroud)

该方法适用于有效T.因此您可以使用SFINAE

template<typename T>
auto call_f_if_available_impl(const T& t, int) -> decltype(call_f(t))
{
    call_f(t);
}

template<typename T>
auto call_f_if_available_impl(const T& t, ...)
{
    // Do nothing;
}

 template<typename T>
 auto call_f_if_available(const T& t)
 {
    call_f_if_available_impl(t, 0);
 }
Run Code Online (Sandbox Code Playgroud)

注意int = 0并且...是订购过载. 演示

-

另一种情况是模板添加特殊参数以应用SFINAE进行专业化:

template <typename T, typename Enabler = void> struct S;
Run Code Online (Sandbox Code Playgroud)

然后

// Specialization only available for T which respect the traits.
template <typename T>
struct S<T, std::enable_if_t<my_type_trait<T>::value>>
{
};
Run Code Online (Sandbox Code Playgroud)


Okt*_*ist 9

如果一个实体可以在 SFINAE 上下文中使用而不会在替换失败时产生硬错误,则该实体被称为 SFINAE 友好的。我假设您已经知道 SFINAE 是什么,因为这本身就是另一个问题。

在 C++ 标准化的背景下,术语“SFINAE 友好”迄今为止已应用于std::result_ofstd::common_type。举个例子:

template <typename T>
void foo(T x, typename std::common_type<T, int>::type y) {}

void foo(std::string x, std::string y) {}

int main()
{
    foo(std::string("hello"), std::string("world"));
}
Run Code Online (Sandbox Code Playgroud)

如果没有 SFINAE-Friendly common_type,这将无法编译,因为std::common_type<std::string, int>::type会在模板参数替换期间产生硬错误。common_type随着 SFINAE 友好型( N3843 )的引入,这个示例变得格式良好,因为std::common_type<std::string, int>::type会产生替换失败,从而将过载从可行集中排除。

这是一个类似的例子result_of

template <typename T>
auto bar(T f) -> typename std::result_of<T()>::type { return f(); }

void bar(int n) {}

int main()
{
    bar(42);
}
Run Code Online (Sandbox Code Playgroud)

如果没有 SFINAE-Friendly result_of,这将无法编译,因为std::result_of<int()>::type会在模板参数替换期间产生硬错误。result_of随着 SFINAE 友好型( N3462 )的引入,这个示例变得格式良好,因为std::result_of<int()>::type会产生替换失败,从而将过载从可行集中排除。