繁体   English   中英

CRTP(Curious Recurring Template Pattern)中的模板派生类

[英]Templated derived class in CRTP (Curiously Recurring Template Pattern)

我使用了不能用 g++ 4.2.1 编译的 CRTP,也许是因为派生类本身就是一个模板? 有谁知道为什么这不起作用,或者更好的是,如何使它起作用? 示例代码和编译器错误如下。

资料来源:foo.C

#include <iostream>

using namespace std;

template<typename X, typename D> struct foo;

template<typename X> struct bar : foo<X,bar<X> >
{
  X evaluate() { return static_cast<X>( 5.3 ); }
};

template<typename X> struct baz : foo<X,baz<X> >
{
  X evaluate() { return static_cast<X>( "elk" ); }
};

template<typename X, typename D> struct foo : D
{
  X operator() () { return static_cast<D*>(this)->evaluate(); }
};

template<typename X, typename D>
void print_foo( foo<X,D> xyzzx )
{
  cout << "Foo is " << xyzzx() << "\n";
}

int main()
{
  bar<double> br;
  baz<const char*> bz;

  print_foo( br );
  print_foo( bz );

  return 0;
}

编译器错误

foo.C: In instantiation of ‘foo<double, bar<double> >’:
foo.C:8:   instantiated from ‘bar<double>’
foo.C:30:   instantiated from here
foo.C:18: error: invalid use of incomplete type ‘struct bar<double>’
foo.C:8: error: declaration of ‘struct bar<double>’
foo.C: In instantiation of ‘foo<const char*, baz<const char*> >’:
foo.C:13:   instantiated from ‘baz<const char*>’
foo.C:31:   instantiated from here
foo.C:18: error: invalid use of incomplete type ‘struct baz<const char*>’
foo.C:13: error: declaration of ‘struct baz<const char*>’

CRTP 的想法是让基类知道它的派生类是什么类型——而不是让基类从它的派生类派生。
否则会出现以下情况:

  • Derived派生自Base<Derived> ,其中
  • 派生自Derived ,其中
  • 派生自Base<Derived> ,其中
  • ...

请改用以下内容:

template<typename X, typename D> struct foo // : D
// ...                                         ^ remove that

有一种方法可以使 CRTP 适用于模板派生类,但需要注意的是它应该始终是模板。

#include <iostream>
#include <typeinfo>


template<template <class> class Derived, class T>
struct A{
    void interface(){
        static_cast<Derived<T>*>(this)->impl();
    }
};

template<class T>
struct B: public A<B, T>
{
    void impl(){
        std::cout << "CRTP with derived templates are real\n";
        std::cout << "Tempate argument is " << typeid(T).name() << "\n";
    }
};

int main(void)
{   
    B<char>().interface();
    B<double>().interface();
    B<void>().interface();
    return 0;
}

适用于 gcc 4.4.7 甚至更旧的版本,无法确定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM