2010-06-08 72 views
0

此代碼無法使用g ++ 4.2.1編譯,但在vC++ v8下正常工作。gcc解決方法,同時使用shared_ptr插入std :: set

#include <set> 
typedef std::set<int *> IntPtrSet; 
IntPtrSet iptrSet; 

typedef std::set<shared_ptr<int>> IntPtrSet2; 
IntPtrSet2 iptrSet2; 

void AddIntegers(int& x) 
{ 
    iptrSet.insert(&x); 
    iptrSet2.insert(&x); 
} 

shared_ptr與boost :: shared_ptr或tr1 :: shared_ptr類似。

它會發出以下錯誤,

No matching function for call to std::allocator<shared_ptr<int>>::construct(int**, const shared_ptr<int>&) 
No matching function for call to std::allocator<shared_ptr<int> >::destroy(int **) 

沒有人之前遇到這樣的錯誤?如果是,那麼解決方法是什麼。

下面是完整的錯誤消息:

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:402: error: no matching function for call to 'std::allocator<shared_ptr<int> >::destroy(int**)' 

/Users/mark/Templates/Function/main.cpp:188: instantiated from here 
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:380: error: no matching function for call to 'std::allocator<shared_ptr<int> >::construct(int**, const shared_ptr<int>&)' 
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h:106: note: candidates are: void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = shared_ptr<int>] 

完全模板實例化堆棧:

/Developer/usr/bin/gcc-4.2 -x c++ -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -isysroot 
/Developer/SDKs/MacOSX10.6.sdk -mfix-and-continue -fvisibility-inlines-hidden -mmacosx-version-min=10.6 -gdwarf-2 -iquote /Users/mark/Templates/Function/build/Function.build/Debug/Function.build/Function-generated-files.hmap - I/Users/mark/Templates/Function/build/Function.build/Debug/Function.build/Function-own-target-headers.hmap - I/Users/mark/Templates/Function/build/Function.build/Debug/Function.build/Function-all- target-headers.hmap -iquote /Users/mark/Templates/Function/build/Function.build/Debug/Function.build/Function-project- headers.hmap -F/Users/mark/Templates/Function/build/Debug - I/Users/mark/Templates/Function/build/Debug/include - I/Users/mark/Templates/Function/build/Function.build/Debug/Function.build/DerivedSources/x86 _64 - I/Users/mark/Templates/Function/build/Function.build/Debug/Function.build/DerivedSources -c /Users/mark/Templates/Function/main.cpp -o /Users/mark/Templates/Function/build/Function.build/Debug/Function.build/Objects- normal/x86_64/main.o 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h: In member function 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree_node<_Val>*) [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]': 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:1327: instantiated from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree_node<_Val>*) [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:594: instantiated from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_set.h:141: instantiated from 'std::set<_Key, _Compare, _Alloc>::set() [with _Key = shared_ptr<int>, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Users/mark/Templates/Function/main.cpp:181:從這裏

實例
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:402: error: no matching function for call to 'std::allocator<shared_ptr<int> >::destroy(int**)' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h:110: note: candidates are: void __gnu_cxx::new_allocator<_Tp>::destroy(_Tp*) [with _Tp = shared_ptr<int>] 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h: In member function 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(const _Val&) [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]': 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:840: instantiated from 'typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, const _Val&) [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:988: instantiated from 'std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = shared_ptr<int>, _Val = shared_ptr<int>, _KeyOfValue = std::_Identity<shared_ptr<int> >, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_set.h:307: instantiated from 'std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = shared_ptr<int>, _Compare = std::less<shared_ptr<int> >, _Alloc = std::allocator<shared_ptr<int> >]' 

/Users/mark/Templates/Function/main.cpp:188: instantiated from here 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_tree.h:380: error: no matching function for call to 'std::allocator<shared_ptr<int> >::construct(int**, const shared_ptr<int>&)' 

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/ext/new_allocator.h:106: note: candidates are: void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = shared_ptr<int>] 

這裏是完整的代碼:

#include <iostream> 
template <class T> 
class shared_ptr 
{ 
    private: 
    T* m_p; 
public: 
shared_ptr() throw() : m_p(NULL){} 

shared_ptr(const shared_ptr<T>& p) throw() 
{ 
     m_p = p; 
} 

shared_ptr(T* p) throw() 
{ 
    m_p = p; 
} 

~shared_ptr() throw() 
{ 
    m_p = NULL; 
} 

T* operator=(const shared_ptr<T>& p) throw() 
{ 
    if (m_p != p.m_p) 
    { 
     m_p = p; 
    } 
    return m_p; 
} 

T* operator=(T* p) throw() 
{ 
    if (m_p != p) 
    { 
     m_p = p; 
    } 
    return m_p; 
} 

operator T*() const throw() 
{ 
    return m_p; 
} 

T& operator*() const throw() 
{ 
    return *m_p; 
} 

T** operator&() throw() 
{ 
    return &m_p; 
} 

bool operator!() const throw() 
{ 
    return (m_p == NULL); 
} 

bool operator<(T* p) const throw() 
{ 
    return m_p < p; 
} 

bool operator!=(int nNull) const throw() 
{ 
    return !operator==(nNull); 
} 

bool operator==(int nNull) const throw() 
{ 
    return m_p == NULL; 
} 

bool operator!=(T* p) const throw() 
{ 
    return !operator==(p); 
} 

bool operator==(T* p) const throw() 
{ 
    return m_p == p; 
} 

void CopyTo(T** pp) const throw() 
{ 
    *pp = m_p; 
} 

void Release() throw() 
{ 
    T* p = m_p; 
    if (p) 
    { 
     m_p = NULL; 
    } 
} 

void Attach(T* p) throw() 
{ 
    m_p = p; 
} 

T* Detach() throw() 
{ 
    T* p = m_p; 
    m_p = NULL; 
    return p; 
} 

};

#include <set> 
typedef std::set<int *> IntPtrSet; 
IntPtrSet iptrSet; 

typedef std::set<shared_ptr<int> > IntPtrSet2; 
IntPtrSet2 iptrSet2; 

void AddIntegers(int& x) 
{ 
iptrSet.insert(&x); 

shared_ptr<int> intPtr(new int(3)); 

iptrSet2.insert(intPtr); 
} 


int main (int argc, char * const argv[]) { 


char c; 
std::cin >> c; 
    return 0; 
} 

另外在Dinkumware網站上代碼編譯成功。它沒有使用前面提到的g ++編譯.FYI,我粘貼了下面的Dinkumware網站(http://www.dinkumware.com/exam/default.aspx)的結果。

您的代碼已經使用Microsoft Visual Studio 2005 C++編譯器使用Dinkum Compleat Libraries for VC++包中的Dinkum C++庫編譯爲 。

這是使用上面的代碼在名爲 sourceFile.cpp文件編譯器輸出:


sourceFile.cpp


尺寸sourceFile.exe: 6144噸+ 3584 .rdata + 512d = 10240(2800)

代碼編譯成功! 生成的可執行文件是11 KB。

非常感謝

問候, 馬克

+0

如果你提供完整的錯誤信息,包括模板實例化堆棧這將是很好。 – jpalecek 2010-06-08 12:53:18

回答

4

你的shared_ptr實現看起來很不尋常。

與boost/tr1相比,T **和T *有額外的轉換運算符。隱式轉換爲底層指針類型(T *)只會讓編譯器感到困惑。

在我註釋掉了這些方法後,我不得不修複復制構造函數以實際複製成員方式而不是濫用轉換運算符。它仍然不會作爲共享指針工作,因爲沒有引用計數。

然後,我不得不修復operator<再次採取const shared_ptr<T>& p,因爲隱式轉換導致它編譯,但稍後將編譯器混淆在std::set上。它很困惑,因爲它試圖構建一個shared_ptr,但operator&(我認爲)導致它降級到T**,因此該類型與容器內部的類型不匹配。

通過這些更改,我能夠使用g ++ 4.2成功編譯它。

編輯: 嗯,我能夠編寫一個自定義的分配器編譯,但它似乎不太乾淨,甚至可能無法在所有情況下工作。

template <class T> 
class sh_ptr_alloc : public std::allocator<T> 
{ 
public: 
     typedef size_t  size_type; 

     sh_ptr_alloc() throw() { } 

     template<typename Tp1> 
     sh_ptr_alloc(const sh_ptr_alloc<Tp1>&) throw() { } 

     template<typename Tp1> 
     struct rebind 
     { typedef sh_ptr_alloc<Tp1> other; }; 

template <class Tp1> 
     void 
     deallocate(Tp1* p, size_type) 
     { ::operator delete(p); } 

template <class Tp1> 
     void 
     construct(Tp1** p, const shared_ptr<Tp1>& val) 
     { ::new(p) shared_ptr<int>(val); } 

template <class Tp1> 
     void 
     destroy(Tp1** p) { } 
}; 

設定則是:

typedef std::set<shared_ptr<int>, std::less<shared_ptr<int> >, sh_ptr_alloc<shared_ptr<int> > > IntPtrSet2;

+0

非常感謝您的解決方案:)問題是shared_ptr我使用的是我無權更改的代碼的一部分。許多其他客戶端代碼依賴於隱式轉換運算符。是否有其他解決方法,而不更改shared_ptr? – Mark 2010-06-09 05:56:12

+1

@Mark瞭解。但是也要考慮:如果很多代碼依賴於隱式轉換,請考慮可以在不知情的情況下破解多少代碼,因爲隱式轉換是以意想不到的方式調用的? – 2010-06-09 13:52:52

+0

同意。我會推動使用更好的shared_ptr。感謝您使用自定義分配器的解決方案。 :) – Mark 2010-06-09 19:07:13

0
void AddIntegers(int& x) 
{ 
... 
    iptrSet2.insert(&x); 

這可能失敗,因爲沒有隱式轉換形式int*boost::shared_ptr<int>。你必須手動構造它(注意:對於一個對象,只能構造一個shared_ptr;其他指針必須作爲這個「主」共享指針的副本創建)。

+0

我曾嘗試過,但仍然失敗。發佈完整的錯誤消息和堆棧。謝謝 – Mark 2010-06-08 13:22:22

+0

請看Mark B的回答。 – jpalecek 2010-06-08 17:12:42

1

看起來像從int *到shared_ptr的轉換有問題。我認爲,解決辦法很簡單:

shared_ptr<int> intPtr(&x); 
iptrSet2.insert(intPtr); 
+0

:(它仍然失敗,有相同的兩個錯誤 – Mark 2010-06-08 13:03:24

6

對於(明顯)的原因,沒有來自T*shared_ptr<T>隱式轉換。

例如,下面的代碼失敗:

int i = 3; 
shared_ptr<int> ptr; 
ptr = &i; 

沒有爲一個好理由:shared_ptr擁有它指向的資源。你不能盲目地拋出一些東西進入shared_ptr以獲得可用的內存管理,你必須確保該對象還沒有被其他東西所擁有。

的解決方案是爲使用構造函數或建設者:

shared_ptr<int> ptr(new int(3)); 

shared_ptr<int> ptr = shared_ptr<int>(new int(3)); 

shared_ptr<int> made = make_shared<int>(3); 

的最後一個方法導致了更爲簡潔的指針,但不同的是不會影響到你。

我會強調你的例子很腥。在創建時更好地執行所有權。在這樣的功能中,其他人已經獲得了所有權,並且你正在創造一個巨大的壞bug。

+0

我試過這些,但我仍然得到相同的錯誤信息,我已經發布了確切的錯誤信息 – Mark 2010-06-08 13:16:40

相關問題