Opened 15 years ago

Closed 13 years ago

#1851 closed Bugs (invalid)

Issue with proxies and rvalues

Reported by: Dave Abrahams Owned by: Dave Abrahams
Milestone: Boost 1.36.0 Component: python USE GITHUB
Version: Boost 1.35.0 Severity: Problem
Keywords: Cc:

Description

From https://premier.intel.com/premier/IssueDetail.aspx?IssueID=474910 :

This bug appears in both the linux and Windows versions of the compiler. 
See attached preprocessed file.

The problem appears to be in the obj_moveattr function: it should be
calling the first assignment operator in boost::python::api::proxy

template <class Policies>
inline proxy<Policies> const&
proxy<Policies>::operator=(typename proxy::assignment_self rhs) const
{
return *this = python::object(rhs);
}

but it is not, for some reason. You can see that by adding

this->doesnotexist = 1;

to the above function body, which *should* cause it to fail to compile,
but does not.
  	Issue Communication 	Reply to Issue
Updated by Intel: 4/4/2008 7:04:10 PM
David,

The assignment operator in your example is not being applied to a const 
rvalue.

The assignment operator is being called here:

void obj_moveitem(object& x, object src, object dst)
{
x[dst] = x[src];
}

Even if x was const, the subscript operators inside class 
object_operators return the type const_object_item - not 
const const_object_item.

const_object_item operator[](object_cref) const; // this does not return a constant
object_item operator[](object_cref);


--mark
Feedback from David Abrahams: 4/3/2008 9:16:01 PM
I'm not so interested in G++ compatibility as standard 
conformance. If I understand you correctly, a regular 
(non-const) copy assignment operator applies to const 
rvalues as well as non-const ones? If so, that's very surprising.
Updated by Intel: 4/2/2008 8:10:02 PM
David,

The difference between the Gnu and Intel behaviour can be seen
if you add an explicit default assignment operator to the proxy class, i.e.:

sptxl2-146> diff object.cpp nobject.cpp
+
+ proxy& operator=(const proxy&) {
+ this->indefaultassignmentoperator = 1;
+ return *this;
+ }
+

Now both g++ and icpc have the same behaviour - they choose the above
non constant default assignment operator over the user provided const 
assignment operator.
(i.e neither compiler gives an error message about this->doesnotreallyexist
but instead both compilers complain about this->indefaultassignmentoperator).

So the difference between g++ and icpc is the following - icpc generates
a default copy assignment operator (and chooses it as the best match)
and g++ does not generate one. So which compiler is correct - should
a default copy assignment operator be generated or not?

According to the resolution of the core issue #574 the Intel
compiler is doing the right thing, i.e.:

> Since the point of the definition of copy assignment operator
> is to control whether the compiler generates a default version if the
> user doesn't, I suspect the correct answer is that neither const nor
> volatile cv-qualification on operator= should be allowed for a copy
> assignment operator. A user can write an operator= like that, but
> it doesn't affect whether the compiler generates the default one.

But of course the Intel compiler on Linux needs to match the Gnu 
behaviour so this is a bug
on our part.


--mark
Feedback from David Abrahams: 4/1/2008 4:32:44 PM
I'm sorry; I don't see what being a copy assignment operator 
has to do with it. The proxy object being assigned into is a
const rvalue, and thus, IIUC, only a const member function can
apply to it. If the default-generated copy assignment is a 
non-const function, it shouldn't be found. What am I missing?
Updated by Intel: 3/27/2008 10:10:57 PM
David,

The development team just informed me that the Intel compiler 
is in fact doing the right thing per the language spec, but 
we will emulate gcc's behavior for compatibility purposes. To 
fix the code you should make the 
proxy<Policies>::operator=(proxy& const) function a non constant
member function. By changing:

inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::assignment_self rhs) const

To:


:inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::assignment_self rhs)

The compiler compiles the code.

Thanks,
--mark

$ icc -c -w object.cpp
../../../boost/python/proxy.hpp(69): error: no instance of overloaded function "boost::python::api::proxy<Policies>::operator=" matches the specified type
inline proxy<Policies> const& proxy<Policies>::operator=(typename proxy::assignment_self rhs)
^

compilation aborted for object.cpp (code 2)

For further details please refer to issue #574 on the C++ standards core issues list, i.e.:

574. Definition of "copy assignment operator"
Section: 12.8 [class.copy] Status: review Submitter: Steve Adamczyk Date: 15 April 2006

Is the following a "copy assignment operator?"

struct A {
const A& operator=(const A&) volatile;
};

12.8 [class.copy] paragraph 9 doesn't say one way or the other whether cv-qualifiers on the function are allowed. (A similar question applies to the const case, but I avoided that example because it seems so wrong one tends to jump to a conclusion before seeing what the standard says.)
Since the point of the definition of "copy assignment operator" is to control whether the compiler generates a default version if the user doesn’’t, I suspect the correct answer is that neither const nor volatile cv-qualification on operator= should be allowed for a "copy assignment operator." A user can write an operator= like that, but it doesn't affect whether the compiler generates the default one.
Updated by Intel: 3/25/2008 11:51:37 PM
David,

Thanks for the problem report and the test case. I reproduced the problem and filed a report on this issue. I will let you know when I get an update.

--mark
Intel Developer Support

Change History (2)

comment:1 by Dave Abrahams, 15 years ago

Component: NonePython
Owner: set to Dave Abrahams
Status: newassigned

comment:2 by Dave Abrahams, 13 years ago

Resolution: invalid
Status: assignedclosed

Since I've received no update in many months, and I'm not convinced Boost.Python has a bug, I'm going to close this one as invalid. If that's inappropriate, please feel free to reopen.

Note: See TracTickets for help on using tickets.