考虑一下我有一个std :: vector。
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
我现在想要在某处传递向量并禁止修改其包含的对象的内容,同时仍允许在能够修改容器时使用:
// Acceptable use:
void call_something() {
std::vector<int> blah;
blah.push_back(1);
blah.push_back(2);
// Currently, compiler error because of mismatching types
something(blah);
}
void something(std::vector<const int>& blah)
{
// Auto translates to 'const int'
for ( auto& i : blah ) {
// User cannot modify i.
std::cout << i << std::endl;
}
blah.push_back(blah.size()); // This should be acceptable
blah.emplace_back(); // This should be acceptable
return;
}
// Unacceptable use:
void something_else(const std::vector<int>& blah)
{
// Because of const vector, auto translates to 'const int'
for ( auto& i : blah ) {
std::cout << i std::endl;
}
blah.push_back(blah.size()); // This will present an unacceptable compiler error.
blah.emplace_back(); // This will present an unacceptable compiler error.
return;
}
有一种简单的方法吗?
答案 0 :(得分:2)
没有 easy 方法可以做到这一点。一种方法是将vector
包装在仅公开您要允许的功能的类型中。例如
template<typename T, typename A = std::allocator<T>>
struct vector_wrap
{
using iterator = typename std::vector<T, A>::const_iterator;
using const_iterator = typename std::vector<T, A>::const_iterator;
using size_type = typename std::vector<T, A>::size_type;
vector_wrap(std::vector<T, A>& vec)
: vec_(&vec)
{}
void push_back(T const& value) { vec_->push_back(value); }
void push_back(T&& value) { vec_->push_back(std::move(value)); }
size_type size() { return vec_->size(); }
iterator begin() const { return vec_->cbegin(); }
iterator end() const { return vec_->cend(); }
private:
std::vector<T, A> *vec_;
};
由于上述实现仅存储指向其vector
的指针,因此您必须确保vector
的生命周期长于vector_wrap
的生命周期。
您必须修改something
和something_else
,以便他们以vector_wrap<int>
作为参数。由于vector_wrap::begin
和vector_wrap::end
返回const_iterator
,因此您不得修改for
语句中的现有元素。
答案 1 :(得分:2)
要启用您希望允许的操作,同时防止其他操作,您需要对功能的界面采用细粒度的方法。例如,如果您的调用代码是传递const迭代器(开始和结束)以及后插入器(或自定义后置放置器仿函数),那么您显示的操作子集就是可能的。
template <class Iter, class F>
void something(Iter begin, Iter end, F&& append)
{
using value_type = typename std::iterator_traits<Iter>::value_type;
std::copy(begin, end, std::ostream_iterator<value_type>(std::cout, "\n"));
append(std::distance(begin, end));
append();
return;
}
那说我发现你的例子特别引人注目。你有一个真实的场景,你必须维护可变元素,将一个可变容器传递给一个函数,然后将传递的元素视为不可变的吗?