[cfe-dev] [PATCH] Add APValue::swap
Howard Hinnant
hhinnant at apple.com
Thu Mar 8 16:47:48 PST 2012
On Mar 8, 2012, at 6:05 PM, Benjamin Kramer wrote:
>
> On 08.03.2012, at 23:54, David Blaikie wrote:
>
>> On Thu, Mar 8, 2012 at 2:46 PM, Chris Lattner <clattner at apple.com> wrote:
>>>
>>> On Mar 8, 2012, at 10:45 AM, Howard Hinnant wrote:
>>>
>>>> On Mar 8, 2012, at 1:39 PM, Daniel Dunbar wrote:
>>>>
>>>>> I wanted to make the copy assignment operator private to encourage
>>>>> callers to see if they could use swap instead.
>>>>>
>>>>> My motivation here seems confused though, per subsequent discussion.
>>>>
>>>> I think you're just ahead of your time. Sounds like you're trying to encourage C++11 move assignment. :-) (which I think would be a very good idea, but requires commitment to using C++11)
>>>
>>> I think that it would be completely reasonable (maybe even, "insanely great"?) to put move constructors and assignment operators into llvm & clang if they help performance and are *optional* and ifdef'd on compiler support.
>>>
>>> That would just mean that people with c++'11 compilers can get better build times, but that we remain compatible with older compilers.
>>
>> Usually we have to/have worked around the cases (you know, the usual
>> "don't return big things by value") - the most common things that
>> would benefit would be stuff that this already happens for (eg:
>> std::string). Anyone know of good candidates that we wouldn't
>> reasonably fix for the 98 case by removing the copies?
>
> We have some cases of SmallVectors and DenseMaps of objects with non-trivial copy ctors. It would spare us a few deep copies if the container would move them when it reallocates.
>
> Not sure if it's worth introducing a ton of #ifdef'd code. Sounds like a maintenance nightmare to me.
The #ifdef'ing can be a pain.
I do not want to influence this decision one way or another. But perhaps it would be helpful to relate my experience/practice in libc++ on how I've handled this issue:
For adding move semantics to a class, I just #ifdef around the added members:
class SmallVector
{
public:
// The C++03 constructors & assignment
// ...
#ifdef RVALUE_REFS
SmallVector(SmallVector&&);
SmallVector& operator=(SmallVector&&);
#endif
// ...
};
In /using/ move semantics, I go ahead and define std::move in both C++03 and C++11 modes, and so code always looks like:
x = std::move(y);
For llvm you could do something like:
#ifndef RVALUE_REFS
namespace std
{
template <class T>
inline
const T&
move(const T& t)
{
return t;
}
}
#endif
So in C++03:
x = std::move(y);
is equivalent to:
x = y;
but in C++11 it becomes a move assignment, with no syntax change at the use site. And that is key to keeping this from becoming a total nightmare. #ifdef's are limited to class implementation, and do not leak out to class clients. Class clients can immediately move to C++11 syntax, whether or not they actually get the C++11 optimization.
For factory functions, there is absolutely nothing to do:
SmallVector
make_SmallVector(int data)
{
SmallVector v(data);
// ....
return v;
}
The above syntax works for both C++03 and C++11. Typically in both, RVO kicks in. In the relatively rare cases where RVO does not kick in, C++03 will copy the SmallVector out, and C++11 will move it out. And on the client side, it is also identical:
SmallVector v = make_SmallVector(data);
or
v = make_SmallVector(data);
This may not be the right time to migrate llvm to C++11. But whenever that time comes, the above is a reasonable approach for making that migration.
Howard
More information about the cfe-dev
mailing list