2013-02-22 254 views
5

假設我有下面的類:C++推斷模板參數

template <class T, class U, class V> Foo 
{ 
    ... 
}; 

模板參數具有獨特的映射,所以可以推斷出U和V基於就是T上的其他模板參數。例如,如果T是雙重的,U和V將總是一些類別D1和D2,並且如果T是浮動的,則U和V將總是其他一些類別F1和F2。

考慮到這一點,有沒有一種方法可以只傳入一個模板參數,並讓編譯器推導出另外兩個參數?

我知道簡單的答案是將這些其他類模板化,並將模板參數T傳遞給它們,但我無法使這些類模板化(它們是由工具自動生成的)。

理想我想能夠使用的typedef或#定義,像這樣:

typedef Foo<double> Foo<double, D1, D2> 
typedef Foo<float> Foo<float, F1, F2> 

然而,這些不進行編譯。我想知道是否有一種方法可以使用模板元編程或模板模板參數來解決這個問題,但我似乎無法將這些概念包裹起來,並且我有一種直覺,那裏可能有更簡單的答案。任何人有任何想法?

回答

5

通過Angew給出的答案顯示了正確的方法,但不告訴你如何應付情況下UV不能推導出必須通過實體化的客戶提供。

爲了處理這種情況下,你可以指定默認參數爲模板參數UV

struct D1 { }; struct D2 { }; 
struct F1 { }; struct F2 { }; 

// Primary template 
template<typename T> 
struct deduce_from 
{ 
}; 

// Specialization for double: U -> D1, V -> D2 
template<> 
struct deduce_from<double> 
{ 
    typedef D1 U; 
    typedef D2 V; 
}; 

// Specialization for float: U -> F1, V -> F2 
template<> 
struct deduce_from<float> 
{ 
    typedef F1 U; 
    typedef F2 V; 
}; 

// Give defaults to U and V: if deduce_from is not specialized for 
// the supplied T, and U or V are not explicitly provided, a compilation 
// error will occur 
template< 
    typename T, 
    typename U = typename deduce_from<T>::U, 
    typename V = typename deduce_from<T>::V 
    > 
struct Foo 
{ 
    typedef U typeU; 
    typedef V typeV; 
}; 

這裏是一個簡單的程序測試上述解決方案的正確性:

#include <type_traits> 

int main() 
{ 
    static_assert(std::is_same<Foo<double>::typeU, D1>::value, "Error!"); 
    static_assert(std::is_same<Foo<double>::typeV, D2>::value, "Error!"); 
    static_assert(std::is_same<Foo<float>::typeU, F1>::value, "Error!"); 
    static_assert(std::is_same<Foo<float>::typeV, F2>::value, "Error!"); 

    // Uncommenting this will give you an ERROR! 
    // No deduced types for U and V when T is int 
    /* static_assert(
     std::is_same<Foo<int>::typeU, void>::value, "Error!" 
     ); */ 
    static_assert(
     std::is_same<Foo<int, bool, char>::typeU, bool>::value, "Error!" 
     ); // OK 
    static_assert(
     std::is_same<Foo<int, bool, char>::typeV, char>::value, "Error!" 
     ); // OK 
} 
+0

謝謝!這工作完美。 – thompsonja 2013-02-22 15:36:59

+0

@thompsonja:很高興幫助:-) – 2013-02-22 15:42:41

6

你可以擺脫UV,像這樣:

template <typename T> 
struct Foo 
{ 
    typedef typename deduce_from<T>::U U; 
    typedef typename deduce_from<T>::V V; 
}; 

其中deduce_from封裝的推導過程。

+0

像'deduce_from'這樣的類通常被稱爲「特質類」。 – 2013-02-22 14:29:44

+0

謝謝!你的答案與Andy的結合幫助我解決了這個問題。 – thompsonja 2013-02-22 15:37:16