我有一个正在尝试解决的难题,从根本上来说,它可以归结为以下示例:
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;
}
我可以尝试解释上述内容(我已经尝试了大约三次并删除了文本!),但基本上要求是:
- < code>C 必须继承自使用
C
键入的 B
(利用 CRTP),即 B>
- <代码>C是唯一可以实例化
A
(即 A
必须用 C
键入)
-
A
是唯一的可以定义FOO
(FOO
依赖于类型CT
,关系比所呈现的更复杂)
问题(如您所见与上面的代码)是 BAR
类型仅可用在 C
中,当实例化 B
时,这是不完整的,因此 B
看不到模板的 BAR
类型参数 CT
(C
)。不幸的是,在 B
中,类型 BAR
被用作函数的参数和返回类型(即不仅限于函数范围 - 因此我不能简单地将 typedef 移动到功能范围)。
有办法解决这个问题吗?我无法打破上述关系(除非作为最后手段)。大概使用 c++11,我可以使用 auto
并绕过在 B
中使用 BAR
typedef 的需要,但这目前不是还有一个选择。
编辑:根据@bitmasks 的评论,提供了一些更多信息。
-
A
和 B
中的代码在不同情况下用在相当多的二进制文件中,在这种情况下唯一独特的情况是 C
派生自B
,在其他实例中,C
拥有从 B
派生的某个实例。
- 模板参数可以更改(在
A
和 B
中),只要它们可以默认为不需要更改 A< 的现有使用的值即可。 /code> 和 B
。同一组类型必须可用作默认模板参数或某种其他机制。
我在这里使用模板只是因为我需要紧密耦合,并且需要在不同情况下灵活地使用代码。
组件描述:
- 的 typedef 定义
-
A
最好描述为一个容器,FOO
实际上是一个迭代器,它包含的内容由模板参数B< /code> 最好被描述为一个基类,它包含一组函数,这些函数由 C
实例拥有的某些组件调用。在前面的例子中,这些组件被传递了对从 B
派生的事物的引用(并且这些事物也属于 C
),在此例如,我提供了对 C 本身的引用。
主要的复杂性来自于访问容器 A
,之前 B
和 C
之间的关系是 C
有一个 B
的实例,但现在 C
是 B
的一个实例 - 此更改语义上打破了类型注入类的方式。
I have this puzzle which I am trying to solve, and fundamentally it boils down to the following example:
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;
}
I can try to explain the above (I've tried about three times and deleted the text!), but basically the requirements are:
C
must inherit from B
typed with C
(exploiting CRTP), i.e. B<C<>>
C
is the only one that can instantiate A
(i.e. A
has to be typed with C
)
A
is the only one that can define FOO
(FOO
is dependent on the type CT
, the relationship is more complicated than that presented)
The problem (as you can see with the above code) is that the BAR
type is available only within C
and this is incomplete when B
is instantiated, hence B
does not see the BAR
type of the template argument CT
(C<int>
). Unfortunately within B
, the type BAR
is used as arguments to functions, and return types (i.e. not just limited to function scope - as a result I cannot simply move the typedef to function scope).
Is there a way around this? I cannot break the above stated relationships (unless as a last resort). Presumably with c++11, I could use auto
and get around the need to have the BAR
typedef in B
, however this is currently not yet an option.
EDIT: following on from @bitmasks' comment, some more information.
- The code in
A
and B
is used in quite a few binaries in different situations, the only unique situation in this case is that C
derives from B
, in the other instances, C
owns an instance of something derived from B
.
- The template arguments can be changed (in
A
and B
), as long as they can be defaulted to values which doesn't require changing existing uses of A
and B
. The same set of types must be available either as template parameter that is defaulted or some other mechanism.
I'm using templates here simply because I require the tight-coupling and I needed the flexibility to use the code in different situations.
Descriptions of components:
A
is best described as a container, and FOO
really is an iterator, what it contains is defined by a typedef of the template parameter
B
is best described as a base class which contains a set of functions which are called by some components owned by an instance of C
. In the previous cases, those components were passed a reference to things derived from B
(and those things are also owned by C
), in this instance, I'm providing a reference to C
itself.
The main complication arises from accessing the container A
, previously the relationship between B
and C
is that C
has an instance of B
, but now C
is an instance of B
- this change in semantics breaks the way types are injected into the classes.
发布评论
评论(1)
我认为您可以使用默认模板参数来应对循环
typedef
要求。以下内容按预期工作(据我理解您的问题),并为您(几乎)保留了原始代码的所有自由:帮助器模板类型的名称很糟糕,也许您可以找到更好的名称。
核心技巧是有问题的 typedef 的定义被放入一个单独的元容器(即特征容器)中,这样您仍然可以在那里进行任何巫术。
我注释掉了不必要的 typedef(但将它们留在那里,以便您有更好的机会弄清楚我在那里做什么)。
这符合您的需要吗?
I think you can combat the cyclic
typedef
requirement with default template parameters. The following works as intended (as far as I understand your question) and leaves you (almost) all the liberties of your original code:The names of the helper template types are horrible, perhaps you can find better names.
The core trick is that the definition of the problematic
typedef
s is put in a separate meta-container (i.e. a container for traits) such that you can still do any voodoo there.I commented the unnecessary typedefs out (but left them there so you have a better chance to figure out what I'm doing there).
Does that fit your need?