C ++递归类型特征

时间:2012-11-24 13:50:35

标签: c++ templates typetraits

我正在尝试实现一个模板类(此处名为Get<>),给定结构HGet<H>::type类型是H本身,如果< em> qualified-id H::der不存在,否则为Get<H::der>::type。我无法理解以下代码有什么问题:

#include <iostream>
#include <typeinfo>
using namespace std;

template<class U, class V = void>
struct Get
{
  static const char id = 'A';
  typedef U type;
};

template<class U>
struct Get<U,typename U::der>
{
  static const char id = 'B';
  typedef typename Get<typename U::der>::type type;
};

struct H1
{ };
struct H2
{ typedef double der; };
struct H3
{ typedef void der; };
struct H4
{ typedef H2 der; };

void print(char id, const char* name)
{
  cout << id << ", " << name << endl;
}
int main(int , char *[])
{
  print(Get<H1>::id, typeid(Get<H1>::type).name()); // prints "A, 2H1", OK
  print(Get<H2>::id, typeid(Get<H2>::type).name()); // prints "A, 2H2", why?
  print(Get<H3>::id, typeid(Get<H3>::type).name()); // prints "B, v"  , OK
  print(Get<H4>::id, typeid(Get<H4>::type).name()); // prints "A, 2H4", why?
}

我想要一些帮助,使这段代码按预期运行。更具体地说,我希望Get< H2 >::type等于double,而Get< H4 >::type则相同。

2 个答案:

答案 0 :(得分:3)

模板Get<>有一个默认模板参数 - 这非常危险。根据{{​​1}}是否相等Vintvoid,您会得到不同的结果。这就是:

double首先是Get<H2>::typeGet<H2, void>)。现在来检查,是否有专业化。您的B为id='A',后者变为Get<U,typename U::der>。但这与Get<U, double>不匹配,因此选择了Get<H2, void>A让事情变得有趣。然后变体B也是Get<H2>::type并提供更好的匹配。但是,该方法不适用于所有类型。

这就是我实施Get<U, void>的方式:

Get

答案 1 :(得分:2)

虽然我给@ipc答案+1,但对于C ++ 11启用的编译器非常好,对于C ++ 03编译器,你应该使用不同的方法,因为函数的模板参数的默认值不是在C ++ 03中受支持。所以我有这个代码:

template<class U, class V = void>
struct Get
{
    static const char id = 'A';
    typedef U type;
};

template< class T >
struct is_type {
    static const bool value = true;
};

template<class U>
struct Get<U,
    typename std::tr1::enable_if<is_type<typename U::der>::value, void>::type>
{
    static const char id = 'B';
    typedef typename Get<typename U::der>::type type;
};