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)
我可以尝试解释上面的内容(我已经尝试了三次并删除了文本!),但基本上要求是:
C
必须从B
typed with C
(利用CRTP)继承,即B<C<>>
C
是唯一可以实例化的A
(即A
必须输入C
)A
是唯一可以定义的FOO
(FOO
取决于类型CT
,关系比呈现的更复杂)问题(正如您在上面的代码中看到的)是该BAR
类型仅在实例化C
时可用,并且在B
实例化时不完整,因此B
看不到BAR
模板参数的类型CT
(C<int>
).不幸的是B
,类型BAR
被用作函数的参数和返回类型(即不仅限于函数作用域 - 因此我不能简单地将typedef移动到函数作用域).
有没有解决的办法?我无法打破上述关系(除非作为最后的手段).据推测,使用c ++ 11,我可以使用auto
并避免需要使用BAR
typedef B
,但这目前还不是一个选项.
编辑:继续@bitmasks的评论,更多信息.
A
和B
在不同情况下相当多的二进制文件被使用,在这种情况下,唯一特殊的情况是,C
派生从B
,在其他情况下,C
拥有众多来自派生出来的一个实例B
.A
和B
),只要它们能够被默认为不需要改变现有用途值A
和B
.必须提供相同的类型集作为默认的模板参数或其他一些机制.我在这里使用模板只是因为我需要紧耦合,我需要灵活地在不同情况下使用代码.
组件说明:
A
最好描述为一个容器,它FOO
实际上是一个迭代器,它包含的内容由template参数的typedef定义B
最好描述为一个基类,它包含一组函数,这些函数由一个实例拥有的某些组件调用C
.在前面的例子中,那些组件被传递了对从B
(和那些东西也归属C
)派生的东西的引用,在这个例子中,我提供了对它C
自己的引用.并发症主要源于访问容器A
,以前的关系B
,并C
是C
有一个实例的B
,但现在C
是一个实例的B
-这种语义改变破坏类型注入类的方式.
我认为您可以使用默认模板参数来应对循环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(但将它们留在那里,以便您有更好的机会弄清楚我在那里做什么)。
这符合您的需要吗?