operator= could not be generated

J

Jeffrey Walton

Hi All,

I'm working with some C++ code that performs a lot of heap allocations
on typef'd structs, structs, and classes, but does not ensure cleanup.
Many of the classes and structs hide their assignment operator.

I attempted to write a template class to ensure cleanup, but am
receiving the error, "operator= could not be generated".

Two questions. (1) I'm dealting with pointers and not objects. So why
is an assignmnet operator needed? (2) I know the void* hack is
bullshit. How do I accomplish my goals of the delete, and then set the
pointer to NULL.

Thanks,
Jeff

template <class T>
PtrTypeCleanup<T>::ptrTypeCleanup(T*& ptr)
: m_ptr(NULL)
{
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
reinterpret_cast<void*>(m_ptr) = reinterpret_cast<void*>(ptr);
}

template <class T>
PtrTypeCleanup<T>::~PtrTypeCleanup(void)
{
if(m_ptr)
{
// We must delete through the type
delete m_ptr;
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
// void* p = reinterpret_cast<void*>(m_ptr);
// p = NULL;
}
}

template <class T>
void PtrTypeCleanup<T>::Release(void)
{
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
// void* p = reinterpret_cast<void*>(m_ptr);
// p = NULL;
}

template <class T>
T*& PtrTypeCleanup<T>::eek:perator=(const T*& rhs)
{
// No self assignment
if(this == &rhs) { return *this; }

reinterpret_cast<void*>(m_ptr) =
reinterpret_cast<void*>(rhs.m_ptr);
}
 
V

Victor Bazarov

I'm working with some C++ code that performs a lot of heap allocations
on typef'd structs, structs, and classes, but does not ensure cleanup.
Many of the classes and structs hide their assignment operator.

I attempted to write a template class to ensure cleanup, but am
receiving the error, "operator= could not be generated".

Error? Are you sure? Not a warning?
Two questions. (1) I'm dealting with pointers and not objects. So why
is an assignmnet operator needed?

Usually the assignment operator is used when you *assign* to the object
of your class. Since you didn't post any code showing how you operate
on your objects (of type PtrTypeCleanup), I can't be more specific.
Please see FAQ 5.8.
> (2) I know the void* hack is
bullshit. How do I accomplish my goals of the delete, and then set the
pointer to NULL.

Deleting and setting WHAT to NULL? 'm_ptr'? How is it declared?

The assignment operator cannot be generated usually if your class has a
member with an inaccessible assignment operator, or a constant data
member, etc., IOW a member which does not have assignment semantics.

Since you elected not to post the definition of your class, I can't be
more specific. Please see FAQ 5.8.

V
 
J

Jeffrey Walton

Hi Victor,

My apologies again. I missed another detail.....

I'm working with some C++ code that performs a lot of heap allocations
on typef'd structs, structs, and classes, but does not ensure cleanup.
Many of the classes and structs hide their assignment operator.

Two questions. (1) I'm dealting with pointers and not objects. So why
is an assignmnet operator needed?

Usually the assignment operator is used when you *assign* to the object
of your class.  Since you didn't post any code showing how you operate
on your objects (of type PtrTypeCleanup), I can't be more specific.
Here's how this might be used:

CSomeClass* someClass = new someClass;
PtrTypeCleanup<CSomeClass> cleanup(someClass);

// Do useful things with someClass. Upon an exception,
// I'm ensured the class is cleaned up. I'm also ensured
// that the original pointer is NULL in an attempt to
// vet pointer reuse.

Recall from my statement above, CSomeClass might (and probably does)
have a hidden operator=.
Please see FAQ 5.8.
I cringe when I have to do anything with this solution. There are
nearly 900 source files which produce 7 executable modules with
everything inter-twinded. I probably could not give you a concrete
example without including at least 20 source files.

Do you really need concrete examples that compile and link for an
abstract question? Ie, why do I need an operator= when I'm dealing
with pointers.

Jeff
 
J

Jonathan Lee

Here's how this might be used:

CSomeClass* someClass = new someClass;
PtrTypeCleanup<CSomeClass> cleanup(someClass);

// Do useful things with someClass. Upon an exception,
// I'm ensured the class is cleaned up. I'm also ensured
// that the original pointer is NULL in an attempt to
// vet pointer reuse.

If you can change your usage pattern slightly you
could probably get away with using std::auto_ptr or
one of the Boost smart pointers.

Specifically, I think you're going to have a lot of
problems with trying to clear the original pointer.
A better pattern might be

auto_ptr<CSomeClass> cleanup(new CSomeClass);
CSomeClass* someClass = cleanup.get();

In this arrangement, you don't have to actually set
someClass to null. It has a shorter lifetime than
cleanup (unless you reset cleanup or something).

I don't see where operator= enters into it, since
you're assigning pointers, not objects.

--Jonathan
 
J

James Kanze

I'm working with some C++ code that performs a lot of heap allocations
on typef'd structs, structs, and classes, but does not ensure cleanup.
Many of the classes and structs hide their assignment operator.
I attempted to write a template class to ensure cleanup, but am
receiving the error, "operator= could not be generated".
Two questions. (1) I'm dealting with pointers and not objects. So why
is an assignmnet operator needed? (2) I know the void* hack is
bullshit. How do I accomplish my goals of the delete, and then set the
pointer to NULL.

I'm not quite sure what you're trying to accomplish, but.../
template <class T>
PtrTypeCleanup<T>::ptrTypeCleanup(T*& ptr)
: m_ptr(NULL)
{
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
reinterpret_cast<void*>(m_ptr) = reinterpret_cast<void*>(ptr);

This shouldn't compile. The result of a reinterpret_cast is an
rvalue, and the left hand operand of the built-in assignment
operator requires an lvalue.
template <class T>
PtrTypeCleanup<T>::~PtrTypeCleanup(void)
{
if(m_ptr)
{
// We must delete through the type
delete m_ptr;
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
// void* p = reinterpret_cast<void*>(m_ptr);
// p = NULL;
}
}
template <class T>
void PtrTypeCleanup<T>::Release(void)
{
// Most types have their assignment operator hidden.
// Cast so that we can set the bastard to NULL.
// void* p = reinterpret_cast<void*>(m_ptr);
// p = NULL;
}
template <class T>
T*& PtrTypeCleanup<T>::eek:perator=(const T*& rhs)
{
// No self assignment
if(this == &rhs) { return *this; }

reinterpret_cast<void*>(m_ptr) = reinterpret_cast<void*>(rhs.m_ptr);
}

Can we see the complete definition of PtrTypeCleanup, and
possibly an example of its use? As it is, I'm not quite clear
what it is supposed to be doing. (Something like
boost::scoped_ptr, but with an additional level of indirection
on the pointer?)
 
J

James Kanze

On Jul 8, 4:52 pm, Victor Bazarov <[email protected]> wrote:> On 7/8/2010 4:23 PM, Jeffrey Walton wrote:

[...]
Here's how this might be used:
CSomeClass* someClass = new someClass;
PtrTypeCleanup<CSomeClass> cleanup(someClass);

And you want the destructor of cleanup to delete the object?
And maybe clear the pointer. What's wrong with simply:

template<typename T>
class PtrTypeCleanup : boost::noncopiable
{
T*& m_watched;
public:
explicit PtrTypeCleanup(T* clientPtr)
: m_watched(clientPtr) {}
~PtrTypeCleanup()
{
delete m_watched;
m_watched = NULL; // If desired.
}
};
// Do useful things with someClass. Upon an exception,
// I'm ensured the class is cleaned up. I'm also ensured
// that the original pointer is NULL in an attempt to
// vet pointer reuse.
Recall from my statement above, CSomeClass might (and probably does)
have a hidden operator=.

What CSomeClass has is pretty much irrelevant here (although
mostly objects that you allocation dynamically don't support
assignment).
 
J

Jorgen Grahn

I cringe when I have to do anything with this solution. There are
nearly 900 source files which produce 7 executable modules with
everything inter-twinded. I probably could not give you a concrete
example without including at least 20 source files.

I think he expects you to edit it down as needed, not just show a
subset of your solution's files verbatim.
Do you really need concrete examples that compile and link for an
abstract question? Ie, why do I need an operator= when I'm dealing
with pointers.

I suspect that he suspect that you are focusing on the wrong thing,
and that your problem is in the parts you're not showing. Half the
questions posted here these days are like that.

And also your question is based on an impossible premise. You *don't*
need Foo::eek:perator=() if all you do is mess with Foo pointers. All you
need is, I think, the single forward declaration "class Foo;".

/Jorgen
 

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

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top