FiReTiTi
FiReTiTi

Reputation: 5898

Best way to dispatch on the good template function

I have three functions that do almost the same thing, but the process is a little bit different according to the parameters type:

template<typename T> void Func1(const T *in, T *out)
{
    static_assert(std::is_same<T, INT8>::value
                  || std::is_same<T, UINT8>::value
                  || std::is_same<T, INT16>::value
                  || std::is_same<T, UINT16>::value, "");
    //...
}

template<typename T> void Func2(const T *in, T *out)
{
    static_assert(std::is_same<T, INT32>::value || std::is_same<T, UINT32>::value, "");
    //...
}

template<typename T> void Func3(const T *in, T *out)
{
    static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value, "");
    //...
}

But I don't want the user to have to decide which function call, so I try to do it automatically. Unfortunately so far (I am a C++ beginner), the only way I know would be:

template<typename T> void Function(const T *in, T *out)
{
    if (std::is_same<T, UINT8>::value
        || std::is_same<T, UINT16>::value
        || std::is_same<T, INT8>::value
        || std::is_same<T, INT16>::value)
    {
        Func1(in, out);
        return ;
    }

    if ( std::is_same<T,INT32>::value || std::is_same<T,UINT32>::value )
    {
        Func2(in, out);
        return ;
    }

    if ( std::is_same<T,float>::value || std::is_same<T,float>:: double )
    {
        Func3(in, out);
        return ;
    }
}

I find this solution completely ugly, and I would like to know if something better/faster/more elegant is possible?

Upvotes: 4

Views: 1995

Answers (2)

TartanLlama
TartanLlama

Reputation: 65620

You could write a trait to check if a type is appears in a list. This version uses std::disjunction from C++17, but you can just copy-paste the implementation from the link.

template <typename F, typename... T>
using is_one_of = std::disjunction<std::is_same<F, T>...>;

Then use SFINAE with std::enable_if to select the overload (std::enable_if_t is C++14, use typename std::enable_if<...>::type if you're stuck with 11).

template<typename T> 
std::enable_if_t<is_one_of<T, uint8_t, int8_t, uint16_t, int16_t>::value>
Func(const T *in, T *out)
{
    std::cout << "1\n";
}

template<typename T> 
std::enable_if_t<is_one_of<T, uint32_t, int32_t>::value>
Func(const T *in, T *out)
{
    std::cout << "2\n";
}

template<typename T> 
std::enable_if_t<std::is_floating_point<T>::value> 
Func(const T *in, T *out)
{
    std::cout << "3\n";
}

Note that you don't even need Func1, Func2 and Func3, you can just make the different Func overloads do your processing.

Live Demo

Upvotes: 4

Garf365
Garf365

Reputation: 3707

If you use C++11 or greater, you can use type_traits (SFINAE) :

template<typename T>
typename std::enable_if<std::is_same<T, INT8>::value 
            || std::is_same<T, UINT8>::value 
            || std::is_same<T, INT16>::value 
            || std::is_same<T, UINT16>::value>::type Function(const T*in, T*out)
{
    Func1(in, out);
}

template<typename T>
typename std::enable_if<std::is_same<T, INT32>::value 
            || std::is_same<T, UINT32>::value >::type Function(const T*in, T*out)
{
    Func2(in, out);
}

template<typename T>
typename std::enable_if<std::is_same<T, float>::value 
            || std::is_same<T, double>::value >::type Function(const T*in, T*out)
{
    Func3(in, out);
}

Example: http://coliru.stacked-crooked.com/a/b4f000fa6ffa8f19

Or if you can't use C++11 or greater, you can use overload instead of template:

void Function(const UINT8 *int, UINT8 * out)
{
    Func1(in, out);
} 
...
void Function(const UINT32 *int, UINT32 * out)
{
    Func2(in, out);
} 
...

Or you can use template specialization but, in this case, it's not really relevant (I leave it here, because it was in original answer):

template<typename T> Function(const T *in, T *out);

template<> void Function(const UINT8 *in, UINT8 * out)
{
    Func1(in, out);
}

template<> void Function(const INT8 *in, INT8 * out)
{
    Func1(in, out);
}

....

Upvotes: 5

Related Questions