2012-08-27 24 views
4

這是正確使用std :: enable_if嗎? 它的作品,但它是正確的?正確使用std :: enable_if或如何替換它

//*.h file 

template <typename T> 
static typename std::enable_if<std::is_integral<T>::value, T>::type 
randomFrom(const T min, const T max); 


template <typename T> 
static typename std::enable_if<std::is_floating_point<T>::value, T>::type 
randomFrom(const T min, const T max); 

//*.inl file 

template <typename T> 
inline typename std::enable_if<std::is_integral<T>::value, T>::type 
Math::randomFrom(const T min, const T max) 
{ 
    static std::default_random_engine re((unsigned long)time(0)); 
    std::uniform_int_distribution<T> uni(min, max); 
    return static_cast<T>(uni(re)); 
} 

template <typename T> 
inline typename std::enable_if<std::is_floating_point<T>::value, T>::type 
Math::randomFrom(const T min, const T max) 
{ 
    static std::default_random_engine re((unsigned long)time(0)); 
    std::uniform_real_distribution<T> uni(min, max); 
    return static_cast<T>(uni(re)); 
} 

如何重寫它,實現更清潔的界面?像:

template <typename T> 
static T randomFrom(const T min, const T max); 
與升壓

BTW我有這樣的事情: (我不想使用升壓)

typedef typename boost::mpl::if_< 
     boost::is_floating_point<T>, 
     boost::uniform_real<>, 
     boost::uniform_int<>>::type dist_type; 

和整體行爲在單一功能的解決。但是沒有什麼像std::if對嗎?

回答

7

你的用法很好,而且非常地道。

相當於Boost.MPL的if_std::conditional

typedef typename std::conditional< 
     std::is_floating_point<T>::value, 
     std::uniform_real_distribution<T>, 
     std::uniform_int_distribution<T>>::type dist_type; 
+0

對於'std :: conditional',哈哈,+1沒有想過(也沒有讀過MPL的boost部分,我承認)。解決它在一個單一的功能。 –

+0

這正是我一直在尋找的。謝謝! – relaxxx

4

簡單地包裝他們我猜?

template <typename T> 
inline typename std::enable_if<std::is_integral<T>::value, T>::type 
randomFrom_helper(const T min, const T max) 
{ 
    static std::default_random_engine re((unsigned long)time(0)); 
    std::uniform_int_distribution<T> uni(min, max); 
    return static_cast<T>(uni(re)); 
} 

template <typename T> 
inline typename std::enable_if<std::is_floating_point<T>::value, T>::type 
randomFrom_helper(const T min, const T max) 
{ 
    static std::default_random_engine re((unsigned long)time(0)); 
    std::uniform_real_distribution<T> uni(min, max); 
    return static_cast<T>(uni(re)); 
} 


template <typename T> 
T randomFrom(const T min, const T max) 
{ 
return randomFrom_helper(min,max); 
} 
3

一旦你包起來像Mr.Anubis還建議,你甚至可以刪除(有時有點神祕)SFINAE破解和使用超載而不是:

namespace detail 
{ 
    template <typename T> 
    T randomFromImpl(const T min, const T max, const std::true_type&) 
    { 
     //integer implementation 
    } 

    template <typename T> 
    T randomFromImpl(const T min, const T max, const std::false_type&) 
    { 
     //float implementation 
    } 
} 

template <typename T> 
T randomFrom(const T min, const T max) 
{ 
    static_assert(std::is_arithmetic<T>::value, "unsupported type"); 
    return detail::randomFromImpl(min, max, std::is_integral<T>()); 
} 

除此之外,您的std::enable_if使用確實是正確的,即使不是必需的(但我想這是一個品味的問題,如果你更喜歡SFINAE或重載)。

+3

注意比SFINAE觸發一個O(N)模板實例,而標籤調度是O(1)。所以只要有可能,就更喜歡標籤調度:) –