Fab*_*ica 9 c++ iterator set parameter-passing one-definition-rule
cppreference.com给出的std::set容器说明最后包含此注释:
成员类型,
iterator并且const_iterator可以是同一类型的别名。因为iterator可以转换为const_iterator,所以const_iterator应该在函数参数列表中使用它,以避免违反“一个定义规则”。
我不明白这句话。据我了解,集合不允许修改其元素(如果需要更改一个元素,则必须先对其进行修改erase,然后再insert进行新的修改),因此每个集合都iterator可以作为const_iterator。该标准补充说,有可能(但不是必需)它们是同一类型。到目前为止,很明显。
我没有得到的是可能违反“ 一个定义规则”。该规则表示一个函数可以有许多声明,但只能有一个定义。如何违反?假设我有一个set<int>,并且创建了一个将迭代器作为参数的函数。由于它们的工作方式相同,因此我可以选择其类型:set<int>::iterator或set<int>::const_iterator。如果我不听从建议,那会set<int>::iterator怎样?
我已经编写了一个程序来尝试找到答案。基本上有2个函数,一个函数接受an,另一个函数iterator接受a 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);
}
Run Code Online (Sandbox Code Playgroud)
我已经在rextester.com上使用3种最流行的编译器(gcc,clang和MSVC)对此进行了编译:没有警告,并且运行良好。通常,我希望会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) {}
Run Code Online (Sandbox Code Playgroud)
签名中考虑了别名类型,而不是可以为每种类型创建的任意数量的别名。上面两个定义的签名是相同的。
您必须以相同的方式命名函数以获取错误。更改的代码: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) {
      ^
Run Code Online (Sandbox Code Playgroud)