Search code examples
c++classtemplatesc++11enable-if

Template method enable_if specialization


i have following code that does not compile. This are two functions in a template class that takes the arguments

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() {
    // ....
}

I want to have a specialization in a member method depending on what type Ret is.

Has anybody some idea?


Solution

  • SFINAE does not work on non-template functions (member or non-member).

    As Kerrek SB points out, making them non-member function templates will work. Or as Xeo points out, making them member function templates with a defaulted template argument will also work.

    However, this is only working because the two std::enable_if conditions are non-overlapping. If you want to add a different overload for int (say), then you'll find that it doesn't scale as nicely. Depending on what you want to do, tag dispatching generally scales better than SFINAE with multiple alternatives that you want to dispatch on:

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