此代码无法使用g ++ 4.2.1进行编译,但在vc ++ v8下工作正常。
#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 ++进行编译。对不起,我已经粘贴了下面的Dinkumware网站(http://www.dinkumware.com/exam/default.aspx)的结果。
您的代码是使用Microsoft Visual Studio 2005 C ++编译器编译的 来自Dinkum Compleat Libraries for VC ++包的Dinkum C ++库。
这是在名为的文件中使用上述代码的编译器输出 sourceFile.cpp:
sourceFile.cpp
size sourceFile.exe: 6144t + 3584 .rdata + 512d = 10240(2800)
代码编译成功! 生成的可执行文件是11 KB。
非常感谢
此致 标记
答案 0 :(得分:6)
对于(显而易见的)原因,没有从T*
到shared_ptr<T>
的隐式转换。
例如,以下代码失败:
int i = 3;
shared_ptr<int> ptr;
ptr = &i;
有一个很好的理由:shared_ptr
OWNS指出的资源。你不能盲目地将某些东西扔进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);
最后一种方法会导致指针稍微紧凑,但这种差异不太可能影响你。
我会强调你的榜样是可疑的。在创建时,所有权更好地执行。在这样的功能中,很可能其他人已经获得了所有权,并且您正在创建一个大错误。
答案 1 :(得分:4)
您的shared_ptr
实施似乎非常不寻常。
与boost / tr1相比,您有T **和T *的额外转换运算符。隐式转换为底层指针类型(T *)只会让编译器感到困惑。
在我评论出这些方法之后,我不得不修复复制构造函数以实际复制成员而不是滥用转换运算符。它仍然无法作为共享指针工作,因为没有引用计数。
然后我必须修复operator<
再次使用const shared_ptr<T>& p
,因为隐式转换导致编译,但稍后会混淆std::set
上的编译器。它感到困惑,因为它试图构造shared_ptr
,但operator&
(我认为)导致它降级为T**
,因此类型与容器内的类型不匹配。 / p>
通过这些更改,我能够使用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;
答案 2 :(得分:1)
看起来它在从int *到shared_ptr的转换时遇到了麻烦。我认为解决方法非常简单:
shared_ptr<int> intPtr(&x);
iptrSet2.insert(intPtr);
答案 3 :(得分:0)
void AddIntegers(int& x)
{
...
iptrSet2.insert(&x);
这可能会失败,因为int*
到boost::shared_ptr<int>
没有隐式转换形式。你必须手动构建它(并注意:对于一个对象,只能构造一个shared_ptr;其他指针必须作为这个“master”共享指针的副本创建。)