6

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

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;
}

我可以尝试解释上面的(我尝试了大约三遍并删除了文本!),但基本上要求是:

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

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

有没有解决的办法?我不能打破上述关系(除非作为最后的手段)。大概使用 c++11,我可以使用auto并解决在 中使用BARtypedef的需要B,但是目前这还不是一个选项。

编辑:继@bitmasks 的评论之后,提供更多信息。

  1. A和中的代码B在不同情况下用于相当多的二进制文件中,在这种情况下唯一独特的情况是C派生自B,在其他情况下,C拥有派生自的事物的实例B
  2. 模板参数可以更改(在Aand中B),只要它们可以默认为不需要更改 and 的现有用途的AB。同一组类型必须可用作默认的模板参数或某些其他机制。

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

组件说明:

  • A最好将其描述为容器,FOO实际上是一个迭代器,它包含的内容由模板参数的 typedef 定义
  • B最好将其描述为包含一组函数的基类,这些函数C. 在前面的案例中,这些组件被传递了一个对派生自的事物的引用B(并且这些事物也归 拥有C),在这种情况下,我提供了对其C自身的引用。

主要的复杂性来自于访问容器,以前和A之间的关系是有一个实例的,但现在是一个实例- 这种语义上的变化打破了将类型注入类的方式。BCC BC B

4

1 回答 1

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;
}

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

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

我将不必要的 typedef 注释掉(但把它们留在那里,这样你就有更好的机会弄清楚我在那里做什么)。

这符合你的需要吗?

于 2011-12-06T17:00:42.837 回答