【问题标题】:Template method enable_if specialization模板方法 enable_if 特化
【发布时间】:2012-08-13 16:54:48
【问题描述】:

我有以下无法编译的代码。 这是模板类中的两个函数,它们接受参数

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 的类型对成员方法进行专门化。

有人知道吗?

【问题讨论】:

    标签: c++ class templates c++11 enable-if


    【解决方案1】:

    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】:

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

    【讨论】:

    • template&lt;class Rx = Ret&gt; 对于成员函数,请参阅我对 rhalbersma 答案的评论。
    • @Xeo:你的意思是这样我们就不用写&lt;T&gt;了?当然,为什么不:-)
    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多