如何使用模板表达成员之间的约束?
假设我有一个包含一堆成员的结构:
struct foo {
int len;
bar *stuff;
};
碰巧 stuff
将指向一个 bar
数组,长度为 len
。我想将其编码为 stuff
的类型。这样的话:
struct foo {
int len;
DependentLength<bar, &foo::len> stuff;
};
然后我可以实现 DependentLength 使其行为类似于指向 bar 数组的指针,但在尝试查看大于 foo::len 的索引时会断言。但是,我无法实现 DependentLength<&foo::len>::operator[]
因为operator[]只接受一个参数,即索引,并且它需要知道 ' 的位置foo' 对象,以便取消引用成员指针模板参数并进行断言检查。
然而,我碰巧知道 DependentLength 只会在这里用作“foo”的成员。我真正想做的是告诉 DependentLength 在哪里可以找到相对于自身的 len,而不是相对于 foo 指针。所以类似 DependentLength<(char*)&foo::stuff - (char*)&foo::len>; stuff;
,但这不是合法的 C++。是否存在一种好的或失败的邪恶语言黑客可以使这项工作成功?
Say I have a struct with a bunch of members:
struct foo {
int len;
bar *stuff;
};
As it so happens stuff
will point to an array of bar
s that is len
long. I'd like to encode this in stuff
's type. So something like:
struct foo {
int len;
DependentLength<bar, &foo::len> stuff;
};
Then I could implement DependentLength
to behave like a pointer to a bar array but that asserts when trying to looking at an index bigger than foo::len
. However, I can't implement DependentLength<&foo::len>::operator[]
because operator[] only takes one parameter, the index, and it needs to know the location of the 'foo' object in order to dereference the member pointer template parameter and do the assert check.
However, I happen to know that DependentLength will only ever be used here as a member of 'foo'. What I'd really like to do is tell DependentLength where to find len relative to itself, rather than relative to a foo pointer. So something like DependentLength<(char*)&foo::stuff - (char*)&foo::len> stuff;
, but that's not legal C++. Is there a good or failing that evil language hack that could make this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您要求模板根据运行时传递给它们的动态属性执行计算...这不适用于模板,因为它们必须使用允许编译创建代码的值进行实例化在
编译时
由模板参数请求。因此,传递给模板的任何值都必须在编译时(而不是运行时)可解析。您将必须使用动态容器类型。例如,
std::vector
满足您的请求,其中如果超出底层容器的边界,std::vector::at()
函数将引发异常。不幸的是,它不如static_assert
那么方便,但同样,在这种情况下使用static_assert
是不可能的,因为您需要运行时检查边界。此外,std::vector 还包含了operator[]、迭代器、大小查询等的重载。You're asking templates to perform calculations based on dynamic properties passed to them during run-time ... that won't work for templates since they must be instantiated with values that allow the compile to create the code requested by the template parameters at
compile time
. Thus any values passed to a template must be resolvable at compile-time, and not run-time.You're going to have to use a dynamic container type. For instance,
std::vector
meets your request where thestd::vector::at()
function will throw an exception if you exceed the bounds of the underlying container. It's unfortunately not as convenient as astatic_assert
, but again, usingstatic_assert
is impossible for this situation since you need run-time checking for the bounds. Additionally,std::vector
also incorporates an overload foroperator[]
, iterators, queries for it's size, etc.您可以告诉模板要用作长度的成员的偏移量。
编辑2:
想到另一个解决方案。使用仅适用于 foo 的类来提供 size 字段的偏移量,并在定义 foo 后定义其方法,并且可以计算偏移量:
这使得可以在 foo 中添加和删除成员。
You can tell the template the offset of the member to use as length.
Edit 2:
Thought of another solution. Use a class that is good for foo only to supply the offset of the size field and define its method after foo is defined and offsets can be calculated:
This makes it possible to add and remove members from foo.