Reputation: 15040
Consider the following code:
class Helper {
public:
template<typename taResult, typename taParam> static taResult Cast(const taParam par);
};
template<> inline __m256d Helper ::Cast(const __m256i par) {
return _mm256_castsi256_pd(par);
}
template<> inline __m256i Helper ::Cast(const __m256d par) {
return _mm256_castpd_si256(par);
}
I want to add to the Helper
a function to handle casts where the parameter and the return types are equals. All my attempts to specialize/overload so far have failed with different compilation errors.
Something like the following in the class body:
template<typename T> static T Cast(const T par) {
return par;
}
Upvotes: 0
Views: 187
Reputation: 66210
I want to add to the Helper a function to handle casts where the parameter and the return types are equals.
What about using SFINAE to enable/disable a Cast()
version according the value of std::is_same<taResult, taParam>::value
?
A simplified example
#include <iostream>
#include <type_traits>
struct Helper
{
template <typename taR, typename taP>
static std::enable_if_t<false == std::is_same<taR, taP>::value, taR>
Cast (taP const & par)
{ std::cout << "different Cast" << std::endl; return {}; }
template <typename taR, typename taP>
static std::enable_if_t<true == std::is_same<taR, taP>::value, taR>
Cast (taP const & par)
{ std::cout << "equal Cast" << std::endl; return par; }
};
template <>
int Helper::Cast<int, long> (long const & par)
{ std::cout << "int/long Cast" << std::endl; return {}; }
template <>
long Helper::Cast<long, int> (int const & par)
{ std::cout << "long/int Cast" << std::endl; return {}; }
int main()
{
Helper::template Cast<int>(0); // print "equal Cast"
Helper::template Cast<int>(0L); // print "int/log Cast"
Helper::template Cast<long>(0); // print "long/int Cast"
Helper::template Cast<long>("foo"); // print "different Cast"
}
Upvotes: 0
Reputation: 217418
You cannot partial specialize function, and your overload would be ambiguous.
You can add class which you can partial specialize though:
template <typename To, typename From> struct CastImpl;
template <typename T> struct CastImpl<T, T>
{
T operator()(T t) const { return t; }
};
template <> struct CastImpl<__m256d, __m256i>
{
__m256d operator()(__m256i t) const { return _mm256_castsi256_pd(t); }
};
template <> struct CastImpl<__m256i, __m256d>
{
__m256i operator()(__m256d t) const { return _mm256_castpd_si256(t); }
};
and then
class Helper {
public:
template<typename taResult, typename taParam>
static taResult Cast(const taParam par)
{
return CastImpl<taResult, taParam>{}(par);
}
};
Upvotes: 3
Reputation: 206607
You can use a helper class/struct template to implement Helper::Cast
.
Here's a simple program that has uses a few shortcuts to demonstrate the concept.
using __m256d = double;
using __m256i = int;
template<typename taResult, typename taParam> struct RealHelper;
class Helper
{
public:
template<typename taResult, typename taParam> static taResult Cast(const taParam par)
{
return RealHelper<taResult, taParam>::doit(par);
}
private:
};
template <> struct RealHelper<__m256d, __m256i>
{
inline static __m256d doit(const __m256i par)
{
// return _mm256_castsi256_pd(par);
return par;
}
};
template <> struct RealHelper<__m256i, __m256d>
{
inline static __m256i doit(const __m256d par)
{
// return _mm256_castpd_si256(par);
return par;
}
};
template <typename T> struct RealHelper<T, T>
{
inline static T doit(const T par)
{
return par;
}
};
int main()
{
auto v1 = Helper::Cast<int, double>(10);
auto v2 = Helper::Cast<double, int>(20);
auto v3 = Helper::Cast<int, int>(30);
auto v4 = Helper::Cast<double, double>(40);
}
Upvotes: 1
Reputation: 62583
No you can not, because that would be an attempt to partially specialize a function, which is not allowed. Instead, you'd have to use an intermediate template class, which than can be specialized.
I can provide example if needed.
Upvotes: 1