编辑:当我完成对任何感兴趣的人的设计更改后,我将在此处放置一个 github 链接。
背景
我正在用我自己的 64 位编译侵入集内容 3 x 8 的实现替换 boost::intrusive
、intrusive_set
-byte 指向我的容器节点的指针。我的容器有 2^16 个节点的限制,因此我可以将每个节点的大小减少到 4 个字节,并使用 2x 16 位偏移序号(大小减少了 6 倍)。
在下面的示例中,base
是侵入集容器。 衍生
类有一个std::vector >
。显然,对于这种间接级别,我需要在派生中拥有一堆嵌套的 typedef,我想在基类中引用它们。
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;
}
但我无法从基础访问嵌套的 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>’
相反,我必须这样做:
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;
}
这是实现我的用例的唯一方法吗?它只会让事情变得更加冗长。我认为派生也可以从特征派生以节省一些击键。
另一种选择是不使用推导,并将逻辑直接连接到当前推导的内容中。但是,我想单独进行单元测试基地。
edit: I'll put a github link here when I am done altering my design for anyone who is interested.
Background
I'm replacing a boost::intrusive
, intrusive_set
, with my own implementation as 64-bit compiled intrusive-set stuffs 3 x 8-byte pointers into my container nodes. my container has a limit of 2^16 nodes so I can bring it down to 4-bytes per node with 2x 16-bit offset ordinals (which is a 6x reduction of size).
In the example below base
is the intrusive-set container. The derived
class has a std::vector<container_entry_type<entry_type> >
. obviously with this level of indirection I need to have a bunch of nested typedef's in derived, which I'd like to refer to in base.
p.s., the containers are for the AST of data description language. The contained elements are therefore small data types and 3 x 8-bytes is very significant. Especially so since the containers are used to validate data-sets in tight loops.
The problem isolated
I want to achieve the following semantics:
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;
}
But I can't access the nested typedef from the base. This is what clang has to say about the matter:
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>’
Instead I am having to do:
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;
}
Is this the only way to achieve my use-case ? it just makes things a whole lot more verbose. I suppose derived could also derive from traits to save some keystrokes.
Another choice is to not use derivation and to wire the logic straight into what is currently derived. However, I'd like to individually unit test base.
发布评论
评论(3)
另一种可能性(可能会或可能不会节省您的击键次数)是在某些地方不使用父类中派生类的嵌套类型。例如。 而不是
使用
您可以使用 SFINAE 将
T
实际上限制为原始变体允许的类型, For extra point。 (请注意,在嵌套模板内,TWO::dummy
可以自由使用 - 它们仅在在整个事物(包括派生
)被实例化之后才被实例化。 ,所以在天真的版本中,在用其成员函数实例化base
时,衍生
仍然不完整,它没有::dummy
,这就是它失败的原因)Another possibility (that might or might not save you keystrokes) would be not using the derived classes' nested types in the parent in some places. Eg. instead of
you'd use
For extra points, you could use SFINAE to actually limit
T
to the types permissible for the original variant. (Note that inside nested templates,TWO::dummy
can be used freely - they are only instantiated after the whole thing incl.derived
has been, so it works out. In the naive version,derived
is still incomplete at the point of instantiating thebase
with its member functions, it has no::dummy
, which is why it fails)扩展 @jpalecek 的想法,我们可以使该模板参数采用默认参数。但您需要启用 C++0x 才能获取此
http://ideone.com/AXXdW
Extending @jpalecek's idea, we could make that template argument take a default argument. But you need to enable C++0x to get this
http://ideone.com/AXXdW
不需要
traits
类。您可以直接在base
中使用type_key
。但是,您无法避免将类型显式传递给
base
。在实例化base
时,编译器还没有看到provider
中的 typedef(更准确地说:类provider
还没有被编译器识别)。完整——怎么可能呢,因为甚至它的基类还不存在)。There's no need for the
traits
class. You can just usetype_key
directly inbase
.You cannot, however, avoid passing the type explicitly to
base
. At the timebase
is instantiated, the typedef inderived
has not yet been seen by the compiler (more exactly: the classderived
is not yet complete — how could it, given that even its base class doesn't exist yet).