【发布时间】:2018-03-20 14:51:10
【问题描述】:
我的类从不同的常量 STL 向量中收集索引值。问题是,即使这些向量的内容不同且用途不同,它们的索引也是std::size_t 类型,因此人们可能会错误地使用为一个向量存储的索引来访问另一个向量的元素。当索引未与正确的向量一起使用时,是否可以更改代码以产生编译时错误?
代码示例:
#include <iostream>
#include <string>
#include <vector>
struct Named
{
std::string name;
};
struct Cat : Named { };
struct Dog : Named { };
struct Range
{
std::size_t start;
std::size_t end;
};
struct AnimalHouse
{
std::vector< Cat > cats;
std::vector< Dog > dogs;
};
int main( )
{
AnimalHouse house;
Range cat_with_name_starting_with_a;
Range dogs_with_name_starting_with_b;
// ...some initialization code here...
for( auto i = cat_with_name_starting_with_a.start;
i < cat_with_name_starting_with_a.end;
++i )
{
std::cout << house.cats[ i ].name << std::endl;
}
for( auto i = dogs_with_name_starting_with_b.start;
i < dogs_with_name_starting_with_b.end;
++i )
{
// bad copy paste but no compilation error
std::cout << house.cats[ i ].name << std::endl;
}
return 0;
}
免责声明:请不要过分关注示例本身,我知道这很愚蠢,只是为了理解。
【问题讨论】:
-
只使用迭代器而不是索引
-
@Slava:这并不能保证解决问题。混合迭代器不会需要导致编译失败。但是,它比数字索引更好。最终,总会有办法解决这个问题。正确的解决方案是(a)不要弄错,(b)测试来检测你什么时候出错。
-
@Slava 如果向量在内存中被移动或复制,即使它们没有改变元素数量或元素顺序,迭代器也不再正确
-
没错,那么您可以在
std::vector上编写一个瘦包装器,它接受自定义索引(这是size_t上的瘦包装器) -
您也可以在
Range中存储对容器的引用并通过它访问容器。