2017-08-08 107 views
0

考慮下面的代碼:如何針對相同的模板參數類型專門化/重載函數?

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); 
} 

我想添加到Helper一個函數來處理鑄件其中參數和返回類型是平等的。我迄今爲止所有嘗試專門化/重載的失敗都是因爲編譯錯誤。

喜歡的東西在類體內以下幾點:

template<typename T> static T Cast(const T par) { 
    return par; 
} 
+1

它看起來像你的代碼失去了一些模板參數在這裏被複制時;你能證實它是正確的嗎? –

+0

@DanielH:OP使用的專業化。 – Jarod42

+0

那麼,爲什麼不在這裏使用正常的重載呢?你提供了3個重載:一個採用__m256i,一個採用__m256d,另一個採用普通模板,不管你的通用算法是什麼。 –

回答

3

你不能局部特化函數,你的重載是不明確的。

您可以添加類,你可以儘管部分專營:

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); } 
}; 

然後

class Helper { 
public: 
    template<typename taResult, typename taParam> 
    static taResult Cast(const taParam par) 
    { 
     return CastImpl<taResult, taParam>{}(par); 
    } 
}; 
+0

爲什麼部分專門化功能是不允許的? –

+2

@DanielH,因爲它[與函數超載混淆](http://www.gotw.ca/publications/mill17.htm)。 –

+0

OP完全專門化他的功能,這是允許的。 – Jarod42

1

,你不行,因爲那將是一個嘗試部分專業的功能,這是不允許的。相反,你必須使用一箇中間模板類,它可以是專用的。

我可以根據需要提供示例。

1

您可以使用一個輔助類/結構模板,實現Helper::Cast

這是一個簡單的程序,它使用了幾個捷徑來演示這個概念。

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); 
} 
0

我想補充的輔助函數來處理鑄件其中參數和返回類型是平等的。

那麼根據std::is_same<taResult, taParam>::value的值使用SFINAE來啓用/禁用Cast()版本怎麼辦?

一個簡單的例子

#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" 
} 
+0

它給出了編譯錯誤,如果我嘗試針對特定類型(例如'__m256d'和'__m256i')對'Cast()'進行專門化處理。 –

+0

@SergeRogatch - 具有一些專業化的修改示例 – max66