1

次のコードシーケンスが与えられます。

#include <iostream>

using namespace std;

template <typename T>
class Base
{
    public:
        T* t;
        void b() {}
};

class D1:
        public Base<D1>
{
    public:
        int d1;
};

class D2:
        public D1
{
    public:
        int d2;
};

template <typename T>
class Selector
{
    public:

        template <typename U>
        void a(Base<U>& base)
        {
            cout << __LINE__ << endl;
            base.b();
        }

        template <typename U>
        void a(U& u)
        {
            cout << __LINE__ << endl;
        }
};


int main()
{
    D2 derivated;
    Selector<D2> s;
    s.a(derivated);
    return 0;
}

一部のクラス(D2)にベース(Base)があり、D2の親のいずれかを継承しているかどうかを確認したいと思います。Selector私は、最も専門的なメンバー関数をヒットすることができません。

4

2 に答える 2

3

独自の特性を装備して、タイプに祖先としての特性があるかどうかを確認できます。 Base<T>以下は私のために働きます:

template <typename T> struct Foo { };

struct Bar : Foo<Bar> { };

struct Zip : Bar { };

#include <type_traits>

template <typename T>
class derives_from_any_foo
{
    typedef char yes;
    typedef char no[2];

    template <typename U>
    static yes & test(Foo<U> const &);

    static no & test(...);

public:
    static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes);
};

#include <iostream>

int main()
{
    std::cout << "int: " <<  derives_from_any_foo<int>::value << "\n"
              << "Bar: " <<  derives_from_any_foo<Bar>::value << "\n"
              << "Zip: " <<  derives_from_any_foo<Zip>::value << "\n";
}

通常、この種の型チェックのためにオブジェクトインスタンスを要求する必要はありません。すべてが静的です。オブジェクトがある場合は、を使用decltypeしてその型を取得するか、型を推測するヘルパー関数を追加します。

于 2012-11-05T14:05:41.887 に答える
1

これは、 (すなわち)U = D2と比較してより良い候補であるために起こっています。最初の選択肢は常に2番目の選択肢を圧倒するため、同じ関数定義でこれを達成することはできません。U = D1Base<D1>

更新:変更が許可されている場合はclass Selector、以下のSFINAEの方法で微調整して正しく修正してください。

template<bool> struct Bool;
template <typename T, typename = Bool<true> >
class Selector // <---- For general cases
{
public:
   template <typename U>
   void a(U& u)  // <---- choose normal funciton
   {   
     cout << __LINE__ << endl;
   }   
};
template <typename T>
class Selector<T,Bool<IsAnyPublicBaseof<T,Base>::value> >
{ // <---- For the cases like `class D2`
public:
  template <typename U>
  void a(Base<U>& base)  // <--- choose special function
  {   
    cout << __LINE__ << endl;
    base.b();
  }   
};

内部SFINAEがある場合、

template<typename T, template<typename> class Base>
struct IsAnyPublicBaseOf
{
  typedef char (&yes)[2];

  template<typename X>
  static yes Check (Base<X>*);
  static char Check (...);

  static const bool value = (sizeof(Check((T*)0)) == sizeof(yes));
};

これがまさにあなたのコードで動作するデモです。

また、決定するためのオブジェクトを持っている必要はないことにも注意してくださいSelector。asメソッドを作成Selector::a()static、使用法を簡単にします。

Selector<D2>::a(derivated);
于 2012-11-05T14:06:25.437 に答える