基于范围的自定义迭代器:constness问题
Custom iterator in range based for: issue with constness
以下代码基于现代C 编程食谱中的代码,并在VS 2017中编译:
#include <iostream>
using namespace std;
template <typename T, size_t const Size>
class dummy_array
{
T data[Size] = {};
public:
T const & GetAt(size_t const index) const
{
if (index < Size) return data[index];
throw std::out_of_range("index out of range");
}
// I have added this
T & GetAt(size_t const index)
{
if (index < Size) return data[index];
throw std::out_of_range("index out of range");
}
void SetAt(size_t const index, T const & value)
{
if (index < Size) data[index] = value;
else throw std::out_of_range("index out of range");
}
size_t GetSize() const { return Size; }
};
template <typename T, typename C, size_t const Size>
class dummy_array_iterator_type
{
public:
dummy_array_iterator_type(C& collection,
size_t const index) :
index(index), collection(collection)
{ }
bool operator!= (dummy_array_iterator_type const & other) const
{
return index != other.index;
}
T const & operator* () const
{
return collection.GetAt(index);
}
// I have added this
T & operator* ()
{
return collection.GetAt(index);
}
dummy_array_iterator_type const & operator++ ()
{
++index;
return *this;
}
private:
size_t index;
C& collection;
};
template <typename T, size_t const Size>
using dummy_array_iterator = dummy_array_iterator_type<T, dummy_array<T, Size>, Size>;
// I have added the const in 'const dummy_array_iterator_type'
template <typename T, size_t const Size>
using dummy_array_const_iterator = const dummy_array_iterator_type<T, dummy_array<T, Size> const, Size>;
template <typename T, size_t const Size>
inline dummy_array_iterator<T, Size> begin(dummy_array<T, Size>& collection)
{
return dummy_array_iterator<T, Size>(collection, 0);
}
template <typename T, size_t const Size>
inline dummy_array_iterator<T, Size> end(dummy_array<T, Size>& collection)
{
return dummy_array_iterator<T, Size>(collection, collection.GetSize());
}
template <typename T, size_t const Size>
inline dummy_array_const_iterator<T, Size> begin(dummy_array<T, Size> const & collection)
{
return dummy_array_const_iterator<T, Size>(collection, 0);
}
template <typename T, size_t const Size>
inline dummy_array_const_iterator<T, Size> end(dummy_array<T, Size> const & collection)
{
return dummy_array_const_iterator<T, Size>(collection, collection.GetSize());
}
int main(int nArgc, char** argv)
{
dummy_array<int, 10> arr;
for (auto&& e : arr)
{
std::cout << e << std::endl;
e = 100; // PROBLEM
}
const dummy_array<int, 10> arr2;
for (auto&& e : arr2) // ERROR HERE
{
std::cout << e << std::endl;
}
}
现在,错误指向该线
T & operator* ()
说明
'返回':无法从'const t'转换为't&amp;'"
...是从我的范围基于for
的 arr2
上提出的。
为什么编译器选择operator*()?
的无恒定版本。我已经看了很长时间了。我认为这是因为它认为其称之为该操作员的对象不是恒定的:这应该是dummy_array_const_iterator
。但是,通过
template <typename T, size_t const Size>
using dummy_array_const_iterator = const dummy_array_iterator_type<T, dummy_array<T, Size> const, Size>;
...所以我真的不明白发生了什么。有人可以澄清吗?
tia
dummy_array_const_iterator::operator *
应该始终返回 T const &
,无论迭代对象本身的构成如何。
实现此目的的最简单方法可能只是将T const
声明为基础迭代器值类型:
template <typename T, size_t const Size>
using dummy_array_const_iterator = dummy_array_iterator_type<T const, dummy_array<T, Size> const, Size>;
由于您是按值返回迭代器,因此C 类型扣除规则很容易丢失,并且仅将dummy_array_const_iterator
宣布为const dummy_array_iterator_type
的别名是不够的。即以下失败:
#include <type_traits>
struct I { };
using C = I const;
C begin();
int bar()
{
auto x = begin(); // type of x is deduced as I
static_assert(std::is_same<I, decltype(x)>::value, "same"); // PASS
static_assert(std::is_same<decltype(begin()), decltype(x)>::value, "same"); // ERROR
}
我才找到了仅当C
不是恒定时启用T& operator*()
的方法:
template <class Tp = T>
typename std::enable_if<std::is_const<C>::value, Tp>::type const& operator* () const
{
return collection.GetAt(index);
}
template <class Tp = T>
typename std::enable_if<!std::is_const<C>::value, Tp>::type & operator* () const
{
return collection.GetAt(index);
}
我不知道语法(我从https://stackoverflow.com/a/26678178)
相关文章:
- 跟随整数索引列表的自定义类迭代器
- 如何在创建自定义迭代器时获得 std::p air 的第一个和第二个?
- 自定义 STL 兼容迭代器,用于迭代 2D 数组类的列
- 无法使用自定义迭代器进行排序
- 比较迭代器会使程序崩溃,而不会在自定义气泡排序实现中出现错误
- 使用迭代器的自定义比较器函数
- 具有迭代器和自定义步长的循环结束条件
- 在C++中使用带有自定义向量的迭代器
- 指向临时对象的自定义迭代器(延迟加载)
- MSVC++ 17 std::copy 期望自定义迭代器的"operator -"
- 如何使用提升范围将自定义迭代器封装在函数中
- 字符串反向迭代器自追加的持久性
- 如何将 std::num_put 与自定义迭代器一起使用?
- 自定义迭代器:如果 a 和 b 的行为不同,如何正确处理距离计算和相等比较
- 迭代器关系运算符出错(带单独链接和迭代器的自定义哈希表)
- std::sort 在我的自定义迭代器上不起作用
- 为自定义数组实现迭代器
- C++自定义惰性迭代器
- 奇怪的编译器错误,说明我的迭代器未定义
- c++迭代器操作符定义