2013-02-22 115 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

相关问题