繁体   English   中英

为什么传递给函数set :: iterator而不是const_iterator违反了One Definition Rule?

[英]Why does passing to a function a set::iterator instead of a const_iterator violate the One Definition Rule?

cppreference.com给出std::set容器的描述最后包含这个注释:

成员类型iteratorconst_iterator可以是同一类型的别名。 由于iterator可以转换为const_iterator ,因此应在函数参数列表中使用const_iterator以避免违反One Definition Rule。

我不明白这最后一句话。 我理解的是一个集合不允许修改它的元素(如果你需要更改它,你必须erase它然后insert新的const_iterator ),所以每个iterator作为const_iterator 该标准补充说,它们是相同的类型(但不是必需的)。 到目前为止,很清楚。

我没有得到的可能是违反一个定义规则 该规则表明函数可以有许多声明,但只有一个定义。 怎么会违反? 假设我有一个set<int> ,我创建了一个函数,它将迭代器作为参数。 由于它们以相同的方式工作,我可以选择它的类型: set<int>::iteratorset<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违规不需要被诊断 ,所以你不能通过(甚至很多)例子反驳它的存在。

如果别名类型相同,那么它是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM