5

Get<>structure が与えられた場合、修飾された 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>そもそも(with id='A')です。次に、専門分野があるかどうかを確認します。あなたのBはGet<U,typename U::der>どちらになるかGet<U, double>です。しかし、これはどちらと一致しない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 に答える