簡體   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