![](/img/trans.png)
[英]Cast of const_iterator to iterator& in definition of std::set
[英]Why does passing to a function a set::iterator instead of a const_iterator violate the One Definition Rule?
cppreference.com给出的std::set
容器的描述最后包含这个注释:
成员类型
iterator
和const_iterator
可以是同一类型的别名。 由于iterator
可以转换为const_iterator
,因此应在函数参数列表中使用const_iterator
以避免违反One Definition Rule。
我不明白这最后一句话。 我理解的是一个集合不允许修改它的元素(如果你需要更改它,你必须erase
它然后insert
新的const_iterator
),所以每个iterator
作为const_iterator
。 该标准补充说,它们是相同的类型(但不是必需的)。 到目前为止,很清楚。
我没有得到的可能是违反一个定义规则 。 该规则表明函数可以有许多声明,但只有一个定义。 怎么会违反? 假设我有一个set<int>
,我创建了一个函数,它将迭代器作为参数。 由于它们以相同的方式工作,我可以选择它的类型: set<int>::iterator
或set<int>::const_iterator
。 如果我不遵循建议会发生什么,也就是说,我选择set<int>::iterator
?
我写了一个程序试图找到答案。 基本上有两个函数,一个接受一个iterator
,另一个接受一个const_iterator
,我调用它们两次,一次传递一个iterator
,一次传递一个const_iterator
。 这里是:
#include <iostream>
#include <set>
void print_set_iter(std::set<int>::iterator& it) {
std::cout << "Set element from iterator: " << *it << "\n";
}
void print_set_const_iter(std::set<int>::const_iterator& const_it) {
std::cout << "Set element from const_iterator: " << *const_it << "\n";
}
int main() {
std::set<int> primes = {2, 3, 5, 7, 11};
std::set<int>::iterator it = primes.find(3);
std::set<int>::const_iterator const_it = primes.find(5);
print_set_iter(it);
print_set_iter(const_it);
print_set_const_iter(it);
print_set_const_iter(const_it);
}
我使用3个最受欢迎的编译器(gcc,clang,MSVC)在rextester.com上编译了这个:没有警告,它运行正常。 通常我会期望print_set_iter(const_it);
导致错误,但事实并非如此。 是否意味着这三个实现对两个迭代器使用相同的类型? 但即使在这种情况下,即使我发现编译器不对这些迭代器使用相同的类型,我仍然不明白为什么会出现ODR违规。 如果类型不同,禁止转换(从const到非const)应该触发错误,但这与ODR无关。 任何人都可以向我展示这种违规行为的例子,或者解释一下该注释的含义吗?
有两种maybes:
如果别名类型相同,那么它是ODR违规,与此相同:
using type_1 = int;
using type_2 = int;
void func(type_1) {}
void func(type_2) {}
别名类型在签名中考虑,而不是可以为每种类型创建的任意数量的别名。 上面两个定义的签名是相同的。
您必须以相同的方式命名函数以获取错误。 更改的代码: https : //rextester.com/SSNZ54459
错误是
source_file.cpp: In function ‘void print_set_iter(std::set<int>::const_iterator&)’:
source_file.cpp:8:6: error: redefinition of ‘void print_set_iter(std::set<int>::const_iterator&)’
void print_set_iter(std::set<int>::const_iterator& const_it) {
^
source_file.cpp:4:6: note: ‘void print_set_iter(std::set<int>::iterator&)’ previously defined here
void print_set_iter(std::set<int>::iterator& it) {
^
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.