我正在创建一个构造函数,它将接受一对输入迭代器。我希望方法签名具有类似于:
的编译时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语义。在这种情况下,我可能会被迫支付模板税。
答案 0 :(得分:9)
调用者可以简单地将模板与const迭代器一起使用。如果他这样做,并且编译器没有抱怨,则保证该函数不会修改数据。如果它会修改数据,用const迭代器实例化模板会导致错误。
您不必仅仅因为不修改任何内容而强制调用者使用const迭代器。
答案 1 :(得分:2)
怎么样?
#include <vector>
template <class T>
class MyClass{
public:
MyClass(typename T::const_iterator t1,typename T::const_iterator t2){
}
// *EDITED*: overload for pointers (see comments)
MyClass(const T* t1,const T* t2){
}
};
void main(){
std::vector<int> v;
std::vector<int>::const_iterator it1 = v.begin();
std::vector<int>::const_iterator it2 = v.end();
MyClass<std::vector<int> > mv(it1,it2);
// with pointers:
char* c1;
char* c2;
MyClass mc(c1,c2);
}
答案 2 :(得分:2)
您可以简单地创建一个虚拟函数,使用char * const
指针调用模板。如果您的模板试图修改其目标,那么您的虚拟函数将无法编译。然后,您可以将所述虚拟内部放在#ifndef NDEBUG
防护中,以将其从发布版本中排除。
答案 3 :(得分:0)
该向量构造函数通过值接收其参数,这意味着调用者的迭代器在构造函数中使用之前被复制,这当然意味着调用者的迭代器没有任何反应。
输入参数的 const
仅在您通过引用传递时才真正重要。 e.g。
void foo(int& x)
VS
void foo(const int& x)
在第一个示例中,x
的来电者输入可能会被foo
修改。在第二个示例中,它可能不是,因为引用是const
。
答案 4 :(得分:0)
如果你能负担得起,这很容易(但不是很漂亮):
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
template<class It>
void f(It b, It e)
{
using namespace boost;
typedef typename std::iterator_traits<It>::reference reference;
BOOST_STATIC_ASSERT(is_const<typename remove_reference<reference>::type>::value);
}
void test()
{
f((char const*)0, (char const*)0); // Compiles
f((char*)0, (char*)0); // Does not compile
}
编辑:如果您想在签名中对此进行说明,那么通常会使用模板参数的名称:
template<class ConstIt>
void f(ConstIt b, ConstIt e)
...