如何在模板函数签名中要求 const_iterator 语义?
我正在创建一个构造函数,它将采用一对输入迭代器。我希望方法签名具有类似于以下内容的编译时 const
语义:
DataObject::DataObject(const char *begin, const char *end)
但是,我找不到任何这样的示例。 例如,我的 STL 实现的 vector
范围构造函数定义为:
template<class InputIterator>
vector::vector(InputIterator first, InputIterator last)
{
construct(first, last, iterator_category(first));
}
它没有编译时 const
保证。 iterator_category
/ iterator_traits<>
也不包含任何与 const
相关的内容。
有什么办法可以表明向调用者保证我不能修改输入数据?
编辑,2010-02-03 16:35 UTC
作为我如何使用该函数的示例,我希望能够传递一对 char*
指针并根据函数签名知道它们指向的数据不会被修改。
我希望能够避免创建一对 const char* 指针来保证 const_iterator 语义。在这种情况下,我可能会被迫缴纳模板税。
I am creating a constructor that will take a pair of input iterators. I want the method signature to have compile-time const
semantics similar to:
DataObject::DataObject(const char *begin, const char *end)
However, I can't find any examples of this.
For example, my STL implementation's range constructor for vector
is defined as:
template<class InputIterator>
vector::vector(InputIterator first, InputIterator last)
{
construct(first, last, iterator_category(first));
}
which has no compile-time const
guarantees. iterator_category
/ iterator_traits<>
contain nothing relating to const
, either.
Is there any way to indicate to guarantee the caller that I can't modify the input data?
edit, 2010-02-03 16:35 UTC
As an example of how I would like to use the function, I would like to be able to pass a pair of char*
pointers and know, based on the function signature, that the data they point at will not be modified.
I was hoping I could avoid creating a pair of const char*
pointers to guarantee const_iterator semantics. I may be forced to pay the template tax in this case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
调用者可以简单地使用带有 const 迭代器的模板。如果他这样做了,并且编译器不会抱怨,则可以保证该函数不会修改数据。如果它会修改数据,则使用 const 迭代器实例化模板将导致错误。
您实际上不必仅仅因为没有修改任何内容就强制调用者使用 const 迭代器。
The caller can simply use the template with const iterators. If he does, and the compiler doesn't complain, it is guaranteed that the function doesn't modify the data. If it would modify the data, instantiating the template with a const iterator would lead to errors.
You don't really have to force the caller to use const iterators just because you don't modify anything.
您可以简单地创建一个虚拟函数,它使用 char * const 指针调用您的模板。如果您的模板尝试修改其目标,则您的虚拟函数将无法编译。然后,您可以将所述虚拟对象放入
#ifndef NDEBUG
防护中,以将其从发布版本中排除。You could simply create a dummy function which calls your template with
char * const
pointers. If your template attempts to modify their targets, then your dummy function will not compile. You can then put said dummy inside#ifndef NDEBUG
guards to exclude it from release builds.怎么样
What about
该向量构造函数按值接收其参数,这意味着调用者的迭代器在构造函数中使用之前会被复制,这当然意味着调用者的迭代器不会发生任何事情。
仅当您通过引用传递时,输入参数的 const 才真正重要。例如
void foo(int& x)
与
void foo(const int& x)
在第一个示例中,调用者对
x
的输入可能是由foo
修改。在第二个示例中,可能不会,因为引用是 const。That vector constructor is receiving its arguments by value, which means that the caller's iterators are copied before being used in the constructor, which of course means that nothing happens to the caller's iterators.
const
for input arguments only really matter when you are passing by reference. e.g.void foo(int& x)
vs
void foo(const int& x)
In the first example, the caller's input for
x
may be modified byfoo
. In the second example, it may not, as the reference isconst
.如果您能负担得起提升,这很容易(但并不漂亮):
编辑:如果您想在签名中对此进行指示,那么通常会利用模板参数的名称:
This is easy (but not pretty) if you can afford boost:
EDIT: if you want to have and indication about this in your signature then it's common to exploit the name of the template parameter: