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

发生这种情况是因为与(ie )U = D2相比,它是一个更好的候选者。您将无法使用相同的函数定义来实现这一点,因为第一个替代方案总是压倒第二个替代方案。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确定对象。只需制作Selector::a()asstatic方法并使使用简单:

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