Search code examples
c++templatestemplate-specializationenable-if

template specialization using enable_if in function definition


if I have the following function

struct Struct { template<T> void Foo(); }

How can I use enable_if in the function definition without repeating the declaration above?

template<T> typename enable_if<is_class<T>,void>::type Struct::Foo() { ... } // error: Struct has no member `Foo<T>`
template<T> typename enable_if<!is_class<T>,void>::type Struct::Foo() { ... } // error: Struct has no member `Foo<T>`

enable_if<is_class<T>,void> is just an example but is there a way to not repeat the declaration with multiple enable_if definitions?

it seems I'm forced to do this

struct Struct
{ 
   template<T> typename enable_if<is_class<T>,void>::type Foo();
   template<T> typename enable_if<!is_class<T>,void>::type Foo();
}

Solution

  • The easiest way to not have to repeat yourself too much is to define them inline:

    #include <type_traits>
    
    struct Struct {
        template<class T>
        std::enable_if_t<std::is_class_v<T>> Foo() { /* ... */ }
        // same as:
        // std::enable_if_t<std::is_class_v<T>, void> Foo() { /* ... */ }    
    
        template<class T>
        std::enable_if_t<!std::is_class_v<T>> Foo() { /* ... */ }   
        // same as:
        // std::enable_if_t<!std::is_class_v<T>, void> Foo() { /* ... */ }
    };
    

    or with constexpr-if:

    struct Struct {
        template<class T>
        void Foo() {
            if constexpr (std::is_class_v<T>) {
                /* ... */
            } else {
                /* ... */
            }
        }
    };
    

    which makes separating the declaration and definition slightly less verbose:

    struct Struct {
        template<class T>
        void Foo();
    };
    
    template<class T>
    void Struct::Foo() {
        if constexpr (std::is_class_v<T>) {
        } else {
        }
    }