简体   繁体   中英

C++ template function specialization

I have to implement a non-member function isHomogenous(Triple triple) for a template class defined as:

template <typename T1, typename T2, typename T3>
    class Triple
{
public:
    Triple()
    { }
    Triple(const T1 &a, const T2 &b, const T3 &c) : a(a), b(b), c(c)
    { }
...

The isHomogenous function should return a bool value indicating whether all of the three values in the parameter triple are of the same type. I have tried:

template <typename T> bool isHomogenous(Triple<T, T, T> triple) {
    return true;
}

template <typename T1, typename T2, typename T3> bool isHomogenous(Triple<T1, T2, T3> triple) {
    return false;
}

This doesn't work, can you hint me on a solution?

A function template cannot be partially specialized.

One alternative is to define it as a static member function (or in your case just a value!) of a class template, and then just provide an ordinary function template wrapper, like …

#include <type_traits>

template< class T1, class T2, class T3 >
struct Blah {};

namespace detail {
    template< class T1, class T2, class T3 >
    struct IsHomogenous { static bool const yes = false; };

    template< class T >
    struct IsHomogenous< T, T, T > { static bool const yes = true; };
}  // namespace detail

template< class T1, class T2, class T3 >
bool isHomogenous( Blah< T1, T2, T3 > )
{
    return detail::IsHomogenous< T1, T2, T3 >::yes;
}

#include <iostream>
int main()
{
    using namespace std;
    wcout << boolalpha
        << isHomogenous( Blah< double, char, void >() ) << " "
        << isHomogenous( Blah< int, int, int >() )
        << endl;
}

and another way is to use C++11 std::is_same :

#include <type_traits>

template< class T1, class T2, class T3 >
struct Blah {};

template< class T1, class T2, class T3 >
bool isHomogenous( Blah< T1, T2, T3 > )
{
    using std::is_same;
    return is_same< T1, T2 >::value && is_same< T2, T3 >::value;
}

#include <iostream>
int main()
{
    using namespace std;
    wcout << boolalpha
        << isHomogenous( Blah< double, char, void >() ) << " "
        << isHomogenous( Blah< int, int, int >() )
        << endl;
}

You cannot specialize a template function, when you add a specialization the specialized function is actually added to the overload set so it is the same as overloading, and for choosing which function to call the overload resolution rules are used.

If you really want to specialize a template function, delegate to a struct or class with a static member and specialize the template struct instead:

template <typename T>
struct handler
{
   static void perform(T& );
};

template <>
struct handler<int>
{
   static void perform(int) { doStuff(); }
};

And here is the global function (which you want to specialize):

template <typename T>
void function (T& v)
{
   handler<T>::perform(v);
}

Hope this helps.

You could partially specialize a class with a functor that will return the true or false. (or a static member, whatever):

template< class T1, class T2, class T3 >
class Blah {};

template< class T>
struct isHomogenous
{
    const bool operator()() { return false; }
};

template< template <typename,typename,typename> class T, class T1, class T2, class T3 >
struct isHomogenous<T<T1,T2,T3>>
{
    const bool operator()() { return false; }
};



template< template <typename,typename,typename> class T, class T1>
struct isHomogenous<T<T1,T1,T1>>
{
    const bool operator()() { return true; }
};

std::cout << isHomogenous< Blah<double, char, void> >()() << " "
    << isHomogenous< Blah<int, int, int> >()();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM