Has*_*yed 16 c++ boost crtp intrusive-containers
编辑:当我为任何感兴趣的人改变我的设计时,我会在这里放一个github链接.
背景
我更换boost::intrusive,intrusive_set与我自己的实现为64位编译侵入设定的东西3×8个字节的指针到我的容器节点.我的容器有2 ^ 16个节点的限制,所以我可以将它降低到每个节点4个字节,带有2个16位偏移序数(大小减少6倍).
在下面的示例中base是侵入式集合容器.该derived班有一个std::vector<container_entry_type<entry_type> >.显然,对于这种间接级别,我需要在派生中有一堆嵌套的typedef,我想在base中引用它.
ps,容器用于数据描述语言的AST.因此,包含的元素是小数据类型,3 x 8字节非常重要.特别是因为容器用于验证紧密循环中的数据集.
孤立的问题
我想实现以下语义:
template<typename TWO>
class base
{
public:
void foo(typename TWO::dummy & d);
};
template<typename DUMMY>
class derived
: private base< derived<DUMMY> >
{
public:
typedef DUMMY dummy;
};
struct tag{};
int main()
{
derived<tag> foo;
}
Run Code Online (Sandbox Code Playgroud)
但我无法从基础访问嵌套的typedef.这就是clang对此事所说的话:
main.cc: In instantiation of ‘base<derived<tag> >’:
main.cc:9:7: instantiated from ‘derived<tag>’
main.cc:20:16: instantiated from here
main.cc:5:8: error: no type named ‘dummy’ in ‘class derived<tag>’
Run Code Online (Sandbox Code Playgroud)
相反,我必须这样做:
template<typename type_key>
class traits
{
public:
typedef type_key dummy;
};
template<typename TWO, typename type_key>
class base
{
public:
void foo(typename traits<type_key>::dummy & d);
};
template<typename DUMMY>
class derived
: private base< derived<DUMMY>, DUMMY >
{
public:
typedef DUMMY dummy;
};
struct tag{};
int main()
{
derived<tag> foo;
}
Run Code Online (Sandbox Code Playgroud)
这是实现我的用例的唯一方法吗?它只是让事情变得更加冗长.我认为派生也可以从特征中导出来保存一些击键.
另一个选择是不使用派生并将逻辑直接连接到当前派生的内容.但是,我想单独测试基地.
jpa*_*cek 10
另一种可能性(可能会或可能不会保存击键)在某些地方不会在父级中使用派生类的嵌套类型.例如.代替
void foo(typename TWO::dummy & d);
Run Code Online (Sandbox Code Playgroud)
你会用的
template <class T>
void foo(typename T& d);
Run Code Online (Sandbox Code Playgroud)
对于额外点,您可以使用SFINAE实际限制T原始变体允许的类型.(请注意,嵌套模板内部TWO::dummy可以自由使用 - 它们仅在整个事物包含之后被实例化derived,因此它可以解决.在天真的版本中,derived在实例化base其成员函数时仍然是不完整的,它没有::dummy,这就是它失败的原因)
扩展@jpalecek的想法,我们可以使该模板参数采用默认参数.但是你需要启用C++ 0x才能得到它
#include <typeinfo>
#include <cstdio>
template<typename TWO>
class base
{
public:
template <typename X = TWO> // <-- (requires C++0x to have a default)
void foo(typename X::dummy& d)
{
printf("%s\n", typeid(d).name());
}
};
template<typename DUMMY>
class derived
: public base< derived<DUMMY> >
{
public:
typedef DUMMY dummy;
};
struct tag{};
int main()
{
derived<tag> foo;
tag t;
foo.foo(t); // <--- call the function like normal.
}
Run Code Online (Sandbox Code Playgroud)