Reputation: 8238
I have a function template:
//the most generalized template
template<typename typeArg, typename typeRet>
typeRet func(const typeArg &val);
and several specializations for it, which look like:
template<>
someType func(const otherType &val)
{
//code
}
template<>
typeFoo func(const typeBar &val)
{
//more code
}
but it has no default implementation.
Obviously, both types cannot be deduced automatically, so calls look like:
type1 var1 = func<argType,type1>(arg);
What is the proper way to write a default implementation only for the case when types are identical?
I tried some variants:
1st attempt
template<typename theOnlyType, theOnlyType>
theOnlyType func(const typeArg &theOnlyType)
{
//code
}
But it's wrong, because this function has only one template parameter and it doesn't correspond to the call above.
2nd attempt
template<typename type1, typename type2>
type1 func(const type1 &theOnlyType)
{
//code
}
The call becomes ambiguous, candidates are this function and the most generalized template from the first block of code.
Upvotes: 2
Views: 234
Reputation: 96800
After a bit of studying I've come up with a significantly better solution. It involves adding a wrapper class around static methods and dispatching them through a global method:
#include <iostream>
namespace tag
{
template <typename U, typename P>
struct wrapper // default implementation
{
static U foo(P const &)
{
std::cout << "different types";
return U();
}
};
}
namespace tag
{
template <typename T>
struct wrapper<T, T> // specialized
{
static T foo(T const &)
{
std::cout << "same type";
return T();
}
};
}
template <typename U, typename P>
static inline U foo(P const &p)
{
return tag::wrapper<U, P>::foo(p);
}
int main()
{
foo<int>(0);
foo<int>(true);
}
I hope this helps.
Use std::enable_if
with std::is_same
(C++11):
template <typename A, typename B, typename =
typename std::enable_if<std::is_same<A, B>::value>::type>
B foo(const A &) {
}
Or use this version for C++03 and earlier:
template <typename A, typename B> struct foo; // implement for different types
template <typename T> struct foo<T, T> {
T operator()(const T &) {
// default impelentation
}
};
int main() {
foo<int, int> f;
int n;
f( n );
}
I'm sure there's a way to improve this. I tried to use partial specialization with the function but I couldn't get it to work for me.
Upvotes: 3