7.1: Compiler/linker issue with operators

S

Stefan Slapeta

Hi,

I've found some strange behaviour with some smart pointers. Consider this
little sample:

// **********************************************************
struct MyStruct {};

template <typename T>
struct Wrapper
{
explicit Wrapper(T* p) : m_ptr(p) {}
private:
T *m_ptr;
friend bool operator < (const Wrapper <T>& left, const Wrapper <T>&
right);
};

template <class T>
inline bool operator < (const Wrapper <T>& left, const Wrapper <T>& right)
{
return *(left.m_ptr) < *(right.m_ptr); // forward!
}

inline bool operator < (const MyStruct& left, const MyStruct &right)
{ return true; }

int main()
{
MyStruct a, b;
Wrapper<MyStruct> wa(&a), wb(&b);

wa < wb;
}
// **********************************************************


There is a wrapper class (that could be a smart pointer) which forwards
operator < to its wrapped class.
This code is compiled without problems but the linker complains about an
unresolved external, which is very strange:

error LNK2019: unresolved external symbol "bool __cdecl operator<(struct
Wrapper<struct MyStruct> const &,struct Wrapper<struct MyStruct> const &)"
(??M@YA_NABU?$Wrapper@UMyStruct@@@@0@Z) referenced in function _main



Regards, Stefan
 
C

Carl Daniel [VC++ MVP]

Stefan said:
Hi,

I've found some strange behaviour with some smart pointers. Consider
this little sample:



This should be an FAQ for VC7.1 :)

The problem is, your code is not conforming, and VC7 accepted it. You need
to make a slight change to make it standard conforming. As posted, your
code declares a non-template operator < as a friend, then provides a
templated operator < that has the same signature. Unfortunately, VC7
accepted this, but it's not valid according to the standard.

-cd

// **********************************************************
struct MyStruct {};

/* +++ You need these forwards +++ */
template <class T> struct Wrapper;
template <class T> inline bool operator < (
const Wrapper<T>& left,
const Wrapper<T>& right
);

template <typename T>
struct Wrapper
{
explicit Wrapper(T* p) : m_ptr(p) {}
private:
T *m_ptr;

/* +++ You need to delcare an instantiation of the
operator template as a friend +++ */
friend bool operator < <T> (
const Wrapper& left,
const Wrapper& right
);
};

template <class T>
inline bool operator < (
const Wrapper <T>& left,
const Wrapper <T>& right
)
{
return *(left.m_ptr) < *(right.m_ptr); // forward!
}

inline bool operator < (
const MyStruct& left,
const MyStruct &right
)
{
return true;
}

int main()
{
MyStruct a, b;
Wrapper<MyStruct> wa(&a), wb(&b);

wa < wb;
}
// **********************************************************

-cd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top