crtp和类型可见性

Nim*_*Nim 6 c++ templates crtp

我有这个难题,我试图解决,从根本上归结为以下示例:

template <typename CT>
struct A
{
  typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
};

template <typename CT>
struct B
{
  typedef typename CT::BAR BAR;

  BAR foo() {}
};

template <typename DT>
struct C : B<C<DT> >
{
  typedef DT VALUE_T;

  typedef typename A<C>::FOO BAR;
};

int main () {
  C<int> c;
}
Run Code Online (Sandbox Code Playgroud)

我可以尝试解释上面的内容(我已经尝试了三次并删除了文本!),但基本上要求是:

  1. C必须从Btyped with C(利用CRTP)继承,即B<C<>>
  2. C是唯一可以实例化的A(即A必须输入C)
  3. A是唯一可以定义的FOO(FOO取决于类型CT,关系比呈现的更复杂)

问题(正如您在上面的代码中看到的)是该BAR类型仅在实例化C时可用,并且在B实例化时不完整,因此B看不到BAR模板参数的类型CT(C<int>).不幸的是B,类型BAR被用作函数的参数和返回类型(即不仅限于函数作用域 - 因此我不能简单地将typedef移动到函数作用域).

有没有解决的办法?我无法打破上述关系(除非作为最后的手段).据推测,使用c ++ 11,我可以使用auto并避免需要使用BARtypedef B,但这目前还不是一个选项.

编辑:继续@bitmasks的评论,更多信息.

  1. 该代码AB在不同情况下相当多的二进制文件被使用,在这种情况下,唯一特殊的情况是,C派生从B,在其他情况下,C拥有众多来自派生出来的一个实例B.
  2. 模板参数可以改变(AB),只要它们能够被默认为不需要改变现有用途值AB.必须提供相同的类型集作为默认的模板参数或其他一些机制.

我在这里使用模板只是因为我需要紧耦合,我需要灵活地在不同情况下使用代码.

组件说明:

  • A最好描述为一个容器,它FOO实际上是一个迭代器,它包含的内容由template参数的typedef定义
  • B最好描述为一个基类,它包含一组函数,这些函数由一个实例拥有的某些组件调用C.在前面的例子中,那些组件被传递了对从B(和那些东西也归属C)派生的东西的引用,在这个例子中,我提供了对它C自己的引用.

并发症主要源于访问容器A,以前的关系B,并CC 有一个实例B,但现在C 是一个实例B-这种语义改变破坏类型注入类的方式.

bit*_*ask 4

我认为您可以使用默认模板参数来应对循环typedef要求。以下内容按预期工作(据我理解您的问题),并为您(几乎)保留了原始代码的所有自由:

template <typename CT, typename CTVALUE_T = typename CT::VALUE_T>
struct A
{
    //typedef typename CT::VALUE_T FOO; // FOO is dependent on CT
    typedef CTVALUE_T FOO; // FOO is dependent on CT
};

template <typename CT, typename CTBAR = typename CT::BAR>
struct B
{
    //typedef typename CT::BAR BAR;
    typedef CTBAR BAR;

    BAR foo() {return 0;}
};

template <typename DT> struct VALUE_T__from__DT {
  typedef DT VALUE_T;
};

template <typename DT, template <class T> class _C_ > struct BAR__from__DT {
  typedef typename A<_C_<DT> , typename VALUE_T__from__DT<DT>::VALUE_T >::FOO BAR;
};

template <typename DT>
struct C : B<C<DT>, typename BAR__from__DT<DT, C >::BAR >
{
    //typedef DT VALUE_T;

    //typedef typename A<C>::FOO BAR;
};

int main () {
    C<int> c;
    int x = c.foo();
    (void)x;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

辅助模板类型的名称很糟糕,也许您可​​以找到更好的名称。

核心技巧是,有问题的 s 的定义typedef被放入一个单独的元容器(即特征容器)中,这样您仍然可以在那里进行任何巫术。

我注释掉了不必要的 typedef(但将它们留在那里,以便您有更好的机会弄清楚我在那里做什么)。

这符合您的需要吗?