5

我正在尝试实现一个模板类(Get<>在此处命名),给定一个结构,如果限定ID不存在,H则类型Get<H>::typeH自身,否则为。我无法理解以下代码有什么问题: H::derGet<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

4

2 回答 2

3

模板Get<>有一个默认的模板参数——这是非常危险的。取决于是否V相等intvoid或者double你得到不同的结果。这就是发生的事情:

Get<H2>::typeGet<H2, void>在第一位(带有id='A')。现在来检查,是否有它的专业化。你的 BGet<U,typename U::der>变成了Get<U, double>。但这与 whith 不匹配Get<H2, void>,因此A被选中。事情变得有趣Get<H2>::type。那么变体 B 也是Get<U, void>并且提供了更好的匹配。但是,该方法不适用于所有类型。

这就是我实施的方式Get

template<class U>
class Get
{
  template <typename T, typename = typename T::der>
  static typename Get<typename T::der>::type test(int);
  template <typename T>
  static T test(...);
public:
  typedef decltype(test<U>(0)) type;
};
于 2012-11-24T14:10:29.260 回答
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;
};
于 2012-11-24T14:32:25.730 回答