2010-05-17 96 views
0

我有點卡住使用指針委託集。我的代碼如下:指針代表在STL集

void Graph::addNodes (NodeSet& nodes) 
{ 
    for (NodeSet::iterator pos = nodes.begin(); pos != nodes.end(); ++pos) 
    { 
    addNode(*pos); 
    } 
} 

這裏NODESET被定義爲:

typedef std::set<Node_ptr, Node_ptr_Sorting_Predicate> NodeSet; 

上面這段代碼工作完全在我的Windows機器上,但是當我運行在MAC上的同一段代碼,它給了我下面的錯誤:

no matching function for call to ' Graph::addNode(const boost::shared_ptr<Node>&) '

僅供參考,Node_ptr的類型爲:typedef boost::shared_ptr<Node> Node_ptr;

有人可以告訴我爲什麼會發生這種情況嗎?

+0

*有*一個'圖:: ADDNODE(常量的boost :: shared_ptr的&)'方法? – sth 2010-05-17 21:33:59

+0

bool Graph :: addNode(Node_ptr&node) 這是Graph :: addnode()的聲明 – ananth 2010-05-17 21:58:20

+0

@seth:no there'nt。 – ananth 2010-05-17 22:01:19

回答

1

好了,從你的附加信息,這個問題似乎是addNode需要Node_ptr每個非const參考,而什麼樣的編譯器調用函數是const boost::shared_ptr<Node>&(注意const)。讓我解釋一下:

std::set是一個關聯容器。關聯容器以某種順序存儲它們的元素,使用關鍵元素來定義排序。如果您可以在不知道容器的情況下更改密鑰,則會使容器的內部命令失效。這就是爲什麼我認爲解引用std::set<T>::iterator不會返回可修改的左值。 (這意味着你不能改變返回的引用。例如,如果你有一個迭代器posstd::set<int>*pos=42不應該編譯。)
捕捉這是隻有可修改的左值將綁定到非const引用。但*pos返回的不是一個可修改的左值,因此不會。 (因此,在我的示例中,int& r = *pos;將不會編譯。)原因是,如果允許這樣做,則可以通過容器背後的非const引用更改排序鍵,並弄亂容器的內部排序。
這就是爲什麼你的*pos的結果不會綁定到Node_ptr&。而這又是爲什麼編譯器不能調用你的函數。

您的addNode()成員函數是否真的改變了給定的節點?如果不是,則應該採取const Node_ptr&
如果確實如此,則會出現設計問題。你不能改變集合中的元素。你能做的唯一一件事就是從集合中刪除它,改變它,並將其重新添加在

在一個側面說明:VC9確實編譯下面的代碼:

#include <iostream> 
#include <set> 
#include <typeinfo> 
#include <iterator> 

int main() 
{ 
    std::set<int> set; 
    set.insert(5); 
    std::cout << *set.begin() << '\n'; 
    *set.begin() = 3; // this is an error! 
    std::cout << *set.begin() << '\n'; 
    return (0); 
} 

我相信這是VC9中的錯誤。 Comeau拒絕它。


這裏是如何解決的燈謎與編譯器不喊你認爲它應該調用一個函數或從一組重載的調用錯誤的函數。
你認爲應該調用的函數是Graph::addNode(Node_ptr&)。你認爲應該把它的代碼是

addNode(*pos); 

更改代碼,以便它提供了所需的精確參數(S):

Node_ptr& tmp = *pos; 
addNode(tmp); 

現在呼叫絕對應該編譯(或調用正確的過載),如果編譯器認爲*pos不能被分配給Node_ptr&,就應該吠叫。
通常這種策略可以幫助我找出在這種情況下有什麼問題。

+0

hi ... thnx對於不正確格式的回覆。這是我的第一篇文章。 ** pos不會工作,因爲在第一次解除引用後,考慮的對象是boost :: shared_ptr 。 ADDNODE()被聲明爲: 布爾圖:: ADDNODE(Node_ptr和節點) 那我百思不得其解的是,ADDNODE(* POS)工作完全在我的Windows機器上的問題。 由於pos是set(Node_ptr,predicate)的迭代器,因此它默認查看Node_ptr並將其傳遞給addNode()方法。 但在我的MAC中,編譯器無法進行此轉換。我明白了嗎? – ananth 2010-05-17 21:59:32

+0

@ananth:未來:如果編譯器不能調用某個函數,儘管您認爲該函數存在,那麼該函數的簽名是包含在您的問題中的一個重要細節。根據你提供的新信息,我已經改變了我的答案。 – sbi 2010-05-17 22:21:42

+0

嘿感謝....下面的代碼工作: Node_ptr TMP = * POS機; //(*沒有&) addNode(tmp); 任何想法爲什麼VS 2008不會給一個MAC OSX上的錯誤和日食呢?感謝一噸人。 – ananth 2010-05-17 23:07:50

0

如果內存服務,最初的C++規範(1998)允許std :: set返回可修改的迭代器。這帶來了風險 - 迭代器可能會被用來修改存儲的值,因此集合的排序現在被破壞了。我相信該規範的後續版本已經改變了這一點,現在所有集合迭代器都是不可修改的。我們可以使用VC++ 2010尊重新的行爲,並且具有不可修改的集合迭代器(這很煩人,因爲它阻止了不會改變順序並且應該合法的更改)。

但是,之前的版本沒有。這意味着您可以創建不適合使用const註釋的函數,這會導致切換到不同編譯器時出現問題。解決方案是添加必要的const更改。 VC++仍然可以工作(因爲非常量值可以隱式地作爲const來設置),所以其他所有東西都可以。