【问题标题】:What does it mean when one says something is SFINAE-friendly?有人说某事对 SFINAE 友好是什么意思?
【发布时间】:2016-01-27 09:24:19
【问题描述】:

当有人提到某个特定函数、结构或 ... SFINAE 友好时,我无法清楚地理解它的含义。

谁能解释一下?

【问题讨论】:

    标签: c++ sfinae


    【解决方案1】:

    当它允许替换失败而没有硬错误时(如static_assert)。

    例如

    template <typename T>
    void call_f(const T& t)
    {
        t.f();
    }
    

    该函数是为所有T 声明的,即使那些没有f 的函数,所以你不能在call_f&lt;WithoutF&gt; 上执行SFINAE,因为该方法确实存在。 (非编译代码的Demo)。

    有以下变化:

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

    该方法适用于有效的 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);
     }
    

    注意int = 0... 是为了重载。 Demo

    --

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

    template <typename T, typename Enabler = void> struct S;
    

    然后

    // Specialization only available for T which respect the traits.
    template <typename T>
    struct S<T, std::enable_if_t<my_type_trait<T>::value>>
    {
    };
    

    【讨论】:

    • int = 0... 不明确吗?
    • 你的意思是:你不能在call_f&lt;WithoutF&gt;上做SFINAE
    • @TartanLlama 不,这不是因为int...更专业
    • 是的,它是模棱两可的。它不会编译。
    • 这解释了 SFINAE 是什么,但不是 SFINAE 友好的含义(例如 N3462 和 N3843)。
    【解决方案2】:

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

    在 C++ 标准化的上下文中,SFINAE-friendly 一词迄今已应用于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"));
    }
    

    如果没有 SFINAE 友好的common_type,这将无法编译,因为std::common_type&lt;std::string, int&gt;::type 会在模板参数替换期间产生硬错误。随着对 SFINAE 友好的 common_type (N3843) 的引入,这个示例变得结构良好,因为 std::common_type&lt;std::string, int&gt;::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);
    }
    

    如果没有 SFINAE 友好的result_of,这将无法编译,因为std::result_of&lt;int()&gt;::type 会在模板参数替换期间产生硬错误。随着 SFINAE 友好的 result_of (N3462) 的引入,这个示例变得结构良好,因为 std::result_of&lt;int()&gt;::type 产生替换失败,因此从可行集合中排除了重载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2010-10-06
      • 1970-01-01
      • 2013-09-28
      • 1970-01-01
      • 2014-08-10
      • 2014-12-24
      相关资源
      最近更新 更多