[英]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.