【问题标题】:Mixing policy-based design with CRTP in C++在 C++ 中将基于策略的设计与 CRTP 混合
【发布时间】:2011-02-03 05:26:04
【问题描述】:

我正在尝试编写一个基于策略的主机类(即,从其模板类继承的类),其中策略类也由主机类模板化,以便它可以访问它的类型。这可能有用的一个示例是策略(实际上像 mixin 一样使用)使用多态 clone() 方法扩充主机类。这是我正在尝试做的一个最小示例:

template <template <class> class P>
struct Host : public P<Host<P> > {
  typedef P<Host<P> > Base;
  typedef Host* HostPtr;
  Host(const Base& p) : Base(p) {}
};

template <class H>
struct Policy {
  typedef typename H::HostPtr Hptr;
  Hptr clone() const {
    return Hptr(new H((Hptr)this));
  }
};

Policy<Host<Policy> > p;
Host<Policy> h(p);

int main() {
  return 0;
}

不幸的是,这无法编译,在我看来像是循环类型依赖:

try.cpp: In instantiation of ‘Host<Policy>’:
try.cpp:10:   instantiated from ‘Policy<Host<Policy> >’
try.cpp:16:   instantiated from here
try.cpp:2: error: invalid use of incomplete type ‘struct Policy<Host<Policy> >’
try.cpp:9: error: declaration of ‘struct Policy<Host<Policy> >’
try.cpp: In constructor ‘Host<P>::Host(const P<Host<P> >&) [with P = Policy]’:
try.cpp:17:   instantiated from here
try.cpp:5: error: type ‘Policy<Host<Policy> >’ is not a direct base of ‘Host<Policy>’

如果有人能发现一个明显的错误,或者成功地将 CRTP 混合到策略中,我将不胜感激。

【问题讨论】:

    标签: c++ templates polymorphism policy crtp


    【解决方案1】:

    事实上,问题是由于您从策略继承时尚未看到 HostPtr 声明。有一些关于实例化模板可见这些声明的确切语义的讨论,这有相当复杂的问题,请参阅this defect report

    但是在您的情况下,情况很清楚:在类主体之前,没有代码可以看到任何类成员的声明,因此您的代码失败了。您可以将类型作为模板参数传递

    template <template <class,class> class P>
    struct Host : public P<Host<P>, Host<P>* > {
      typedef P<Host<P> > Base;
      Host(const Base& p) : Base(p) {}
    };
    
    template <class H, class Hptr>
    struct Policy {
      typedef Hptr HostPtr;
      HostPtr clone() const {
        return Hptr(new H((Hptr)this));
      }
    };
    

    如果有更多类型,你可以决定传递一个 trait

    template <class Host>
    struct HTraits {
      typedef Host *HostPtr;
      // ...
    };
    
    template <template <class,class> class P>
    struct Host : public P<Host<P>, HTraits< Host<P> > > {
      typedef P<Host<P> > Base;
      Host(const Base& p) : Base(p) {}
    };
    
    template <class H, class Htraits>
    struct Policy {
      typedef typename Htraits::HostPtr HostPtr;
      HostPtr clone() const {
        return Hptr(new H((Hptr)this));
      }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-20
      • 2014-09-30
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多