我试图创建一个is_foo函数,然后可以将其与enable_if一起使用,以确定某个类型是否从某个CRTP基类派生。下面的代码是我尝试实现is_foo函数的尝试,但实际上并不起作用。有人可以告诉我我需要更改以解决此问题吗?

谢谢。

#include <iostream>
#include <type_traits>
#include <functional>

using namespace std;

template <class Underlying, class Extra>
struct Foo
{
    int foo() const { return static_cast<const Underlying*>(this)->foo(); }
};

template<class T>
struct Bar : Foo<Bar<T>, T>
{
    int foo() const { return 42; }
};

template<class T>
struct is_foo { static const bool value = false; };

template<class Underlying, class Extra>
struct is_foo<Foo<Underlying, Extra> > { static const bool value = true; };

template<class T>
void test(const T &t)
{
    cout << boolalpha << is_foo<T>::value << endl;
}

int main()
{
    Bar<int> b;
    test(b);
}

最佳答案

在Foo基础中添加一个typedef:

template < typename Derived >
struct crtp
{
  ...
  typedef int is_crtp;
};

实现has_field检查:
BOOST_MPL_HAS_XXX(is_crtp)

实现您的元功能:
template < typename T >
struct is_crtp_derived : has_is_crtp<T> {};

这是我能想到的唯一能够正确捕获孙子孙女的方法。不过,它容易产生误报,因此您需要选择过于讨厌的名称,以免在其他地方意外使用。您的另一个选择是根据is_base_of实现您的元功能:
template < typename T >
struct is_crtp_derived : std::is_base_of< crtp<T>, T> {};

这当然不会抓到孙子。

10-08 09:45