代码之家  ›  专栏  ›  技术社区  ›  Philipp H.

模板方法enable_if专业化

  •  6
  • Philipp H.  · 技术社区  · 13 年前

    我有以下代码没有编译。 这是模板类中接受参数的两个函数

    typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() {
        // ...
    }
    
    typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() {
        // ....
    }
    

    我想根据Ret的类型对成员方法进行专门化。

    有人知道吗?

    2 回复  |  直到 11 年前
        1
  •  7
  •   TemplateRex    13 年前

    SFINAE不适用于非模板函数(成员或非成员)。

    正如Kerrek SB所指出的,让它们成为非成员函数模板是可行的。或者,正如Xeo所指出的,让它们成为具有默认模板参数的成员函数模板也是可行的。

    然而,这只是因为 std::enable_if 条件是 不重叠 。如果要为添加不同的重载 int (比如),然后你会发现它的规模并没有那么好。根据您想要做的事情,标记调度通常比SFINAE扩展得更好,有多种备选方案供您调度:

    #include<type_traits>
    
    template<typename Ret>
    class Foo
    {
    public:
        void _on_dispatched()
        {
            // tag dispachting: create dummy of either std::false_type or std::true_type
            // almost guaranteed to be optimized away by a decent compiler
            helper_on_dispatched(std::is_void<Ret>()); 
        } 
    
    private:
        void helper_on_dispatched(std::false_type)
        {
            // do stuff for non-void
        }
    
        void helper_on_dispatched(std::true_type)
        {
            // do stuff for void
        }
    };
    
    int main()
    {
        Foo<void>()._on_dispatched();
        Foo<int>()._on_dispatched();
        return 0;
    }
    
        2
  •  3
  •   Kerrek SB    13 年前

    SFINAE仅适用于模板。您的代码可以通过一个小的修改进行编译:

    template <typename Ret>
    typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }
    
    template <typename Ret>
    typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }
    

    用法:

    auto q = _on_dispatched<int>();
    

    当然,您不能推导函数的返回类型,因为它是不可推导的。但是,您可以打包此模板 在…内 另一个模板:

    template <typename T>
    struct Foo
    {
        // insert templates here, maybe privately so
    
        T bar() { return _on_dispatched<T>(); }
    };
    
    推荐文章