views:

139

answers:

2

Hi everybody.

I have a problem concerning nested templates and the overriding of the assignment operator. Say i want to have a refcounting class template _reference. This _reference for now simply holds a pointer to the ref-counted object. The problem now is that this all works fine, as long as im doing this with simple classes or structs. eg. _reference ...,

But now i want to make a class template that is a reference to a std-vector forwarding the class it holds.

Nah, i just post the code: (it doesnt do refcounting and that stuff right now, its just the extraction of the problem i have)

template <typename T>
class _reference
{
private:
    T* p_;

public:

// !!! this assignment seems only to work, when T is no class template already...
void operator= (T* r)     
{
 p_ = r;
}

// WHILE this ALWAYS works as well...
void simplySetIt (T* r)     
{
 p_ = r;
}
};

template <typename T>
class _ref_vector : public _reference<vector<T> >
{
};

void test2 ()
{
_reference<vector<long> > ref_ptr2;
_ref_vector<long>         ref_ptr3;

ref_ptr2 = new vector<long>;                    // works fine.

ref_ptr3 = new vector<long>;          // BUT: THIS doesnt work
    ref_ptr3.simplySetIt (new vector<long>);    // WHILE: this works fine...
}

MSVC-Error:

error C2679: binary '=' : no operator found which takes a right-hand operand of type 
'std::vector<_Ty> *' (or there is no acceptable conversion)

GCC-Error:

error: no match for 'operator=' in 'ptr3 = (((const stlp_std::allocator<long int>&)
((const stlp_std::allocator<long int>*)(& stlp_std::allocator<long int>()))), 
(((stlp_std::vector<long int, stlp_std::allocator<long int> >*)operator new(12u)), 
((<anonymous> != 0u) ? (<anonymous>->stlp_std::vector<_Tp, _Alloc>::vector [with 
_Tp = long int, _Alloc = stlp_std::allocator<long int>]
(<anonymous>), <anonymous>) : <anonymous>)))'

So please can anybody explain me why the assignment operator doesnt work here, while the simplySetIt - function does ?

+6  A: 

The base operator= gets hidden by implicit assignment operators, so that it doesn't take part in the overloading anymore. You need to write _ref_vector as

template <typename T>
class _ref_vector : public _reference<vector<T> >
{
  using _reference<vector<T> >::operator=;
};

As there is no compiler-added version of simplySetIt, lookup will find it in the base class.

Martin v. Löwis
Add `public` keyword to make it working.
Kirill V. Lyadvinsky
Awesome - that solved it for me: Actually i had to put a public: in front of the using, but now it works fine. Thanx Martin.
Roman Pfneudl
Hmm. It works fine without public for me, in gcc 4.3.4.
Martin v. Löwis
ah yeah - right: in g++ it works without public. But msvc starts whining without.
Roman Pfneudl
A: 

As the standard says (13.5.3):

Because a copy assignment operator operator= is implicitly declared for a class if not declared by the user (12.8), a base class assignment operator is always hidden by the copy assignment operator of the derived class.

SadSido