Etherealone
Etherealone

Reputation: 3558

C++ std::enable_if in a class template, for a member function

The problem is simple. I have a header file with include guards and a implementation file .impl. Header file includes implementation file. I want to do the following:

Header file:

template<size_t N>
class A
{
  void func();
};

.impl file:

template<size_t N>
typename std::enable_if<(N <= 5), void>::type A<N>::func() { ... }

template<size_t N>
typename std::enable_if<(N > 5), void>::type A<N>::func() { ... }

However I am yet to be good with std::enable_if and it seems to fail to find the prototype for func because I change the function signature by changing the return type. How can I have different implementations while providing the user with one function for the interface.

This is essentially MCU register modifier that operates on two registers because one does not have the capacity. I'd rather not use any dirty offsets based on N inside the function and depend on plain structure. Also I'd rather not use helper functions which would complicate things if it is possible without them.

Upvotes: 2

Views: 2427

Answers (2)

user2033018
user2033018

Reputation:

You can use tag dispatching instead:

template <size_t N>
class A
{
    void func()
    {
        do_func(std::integral_constant<bool, (N > 5)>{});
    }

    void do_func(std::true_type) { /* handles the N > 5 case */ }
    void do_func(std::false_type) { /* handles the N <= 5 case */ }
};

Upvotes: 7

user2249683
user2249683

Reputation:

You might delegate:

#include <iostream>

template<std::size_t N>
class A
{
    private:
    template <std::size_t I>
    typename std::enable_if<(I <= 5)>::type
    f() { std::cout << "Small\n"; }

    template <std::size_t I>
    typename std::enable_if<(I > 5)>::type
    f() { std::cout << "Big\n"; }

    public:
    void func() { f<N>(); }
};

int main()
{
    A<1> small;
    small.func();
    A<10> big;
    big.func();
}

And if you trust your compiler optimizations:

template<std::size_t N>
class A
{
    private:
    void small() { std::cout << "Small\n"; }
    void big() { std::cout << "Big\n"; }

    public:
    void func() {
        if(N <= 5) small();
        else big();
    }
};

Upvotes: 4

Related Questions