c++ copy-assignment move-assignment ambiguity - c++11

In C++11, we get an ambiguity error from the compiler (g++) if we make the following definitions:
C& operator=(C rhs)
{
swap(*this, rhs);
return *this;
}
C& operator=(C&& rhs)
{
swap(*this, rhs);
return *this;
}
It is not entirely clear to me why there is an ambiguity. In my understanding, the compiler can tell apart what is an rvalue object and what is not at compile time. So it could make a decision to call the latter for rvalue objects and the former for lvalue objects. I am probably missing something basic but an explanation would be great.

The argument must be passed through const reference to resolve the ambiguity.
C& operator=(const C& rhs)
{
swap(*this, C(tmp));
return *this;
}
Since your class C has a moving constructor C::C(C&&) (I think it is so, you did not provide Minimal, Complete, and Verifiable example) then it causes the ambiguity between operator=(C rhs) and operator=(C&& rhs).

Related

clang -Wglobal-constructors behavior regarding copy/move constructor

This code produces a warning: "declaration requires a global constructor [-Wglobal-constructors]"
// Compile with -Wglobal-constructors
class T {
public:
constexpr T(int* p) : ptr_(p) {}
T(const T& other) : T(other.ptr_) {}
private:
int* ptr_;
};
struct MyStruct {
int x;
T y;
};
MyStruct s[] {{ 123, nullptr },{ 234, nullptr }};
I thought adding constexpr T(std::nullptr_t) : ptr_(nullptr) {} would take care of it, but no. Instead, making the copy constructor constexpr does, which puzzles me. Same applies to a move constructor, if there was one.
Turns out that this behavior continues until C++14, but is no longer the case in C++17, where copy elision covers this case.

C++11 Getting error 'enum-type' does not name a type with boost 1.59 fileSystem

I am getting below error while compiling my code with C++11.
With previous standard It was working fine no compilation issue. (C++03)
signature of function:
boost::filesystem::copy_option::enum_type myFunc()
Error:
‘enum-type’ in ‘enum class boost::filesystem::copy_option’ does not name a type
boost version : 1.59
compiler : gcc version: 4.8.5
I am thinking this might be due to enum class in C++11.
However I dont have any clues how to fix this.
If we look at the v. 1.59.0 Boost Filesystem documentation, we find that boost::filesystem::copy_option is defined as:
enum class copy_option
{
none
fail_if_exists = none,
overwrite_if_exists
};
But enum class is a C++11 feature, so how did including that header ever work in C++03 mode at all? Let's take a peek at the header boost/filesystem/header.hpp, where we see copy_option is defined (inside boost::filesystem) as:
BOOST_SCOPED_ENUM_START(copy_option)
{none=0, fail_if_exists = none, overwrite_if_exists};
BOOST_SCOPED_ENUM_END
A bit of searching turns up that BOOST_SCOPED_ENUM_START and BOOST_SCOPED_ENUM_END are part of the Boost.Core library. The scoped_enum reference page explains that its purpose is "to generate C++11 scoped enums if the feature is supported by the compiler, otherwise emulate it with C++03 constructs". It also says BOOST_SCOPED_ENUM_START and BOOST_SCOPED_ENUM_END are deprecated. So let's look a bit back in time.
As far as I can tell, these macros first appeared without any documentation besides the header file itself in Boost 1.40.0 boost/detail/scoped_enum_emulation.hpp. It was used for the same purpose from Boost.Filesystem.
At the time, there was no copy_option::none value. So if Boost.Config automagically defined BOOST_NO_SCOPED_ENUMS, the enum definition expanded to C++03 compatible code:
struct copy_option { enum enum_t
{ fail_if_exists, overwrite_if_exists };
};
Or if BOOST_NO_SCOPED_ENUMS was not defined, the same definition expanded to C++0x-only code (this was before C++11 was official):
enum class copy_option
{ fail_if_exists, overwrite_if_exists };
Both allow and require writing for example copy_option::overwrite_if_exists. But with one problem: In C++03 mode, the type of that value is copy_option::enum_t, but in C++0x mode, the type is just copy_option. So the scoped_enum_emulation.hpp header defined a third macro BOOST_SCOPED_ENUM(EnumName) which expands to EnumName::enum_t in C++03 mode or just EnumName in C++0x mode. Though the C++03 version still has some issues such as implicit conversion to integer types....
To get code that would work in either case, it was recommended to use BOOST_SCOPED_ENUM(EnumName) whenever you need a variable declaration, function parameter, or function return type to be the scoped enum type. This will still work, so you could fix your issue by writing
BOOST_SCOPED_ENUM(boost::filesystem::copy_option) myFunc();
But there are now other options to consider too.
Boost 1.44.0 switched from using enum_t to enum_type. So this is the oldest your code could have started with.
Boost 1.50.0 changed the definition of the old macros BOOST_SCOPED_ENUM_START and BOOST_SCOPED_ENUM_END, made them deprecated, and introduced the new macros BOOST_SCOPED_ENUM_DECLARE_BEGIN and BOOST_SCOPED_ENUM_DECLARE_END instead. They also introduced some documentation under Boost.Thread, which apparently also started using it. Boost.Filesystem's copy_option still used the old macros, but the C++03 expansion with BOOST_NO_SCOPED_ENUMS defined became:
struct copy_option {
typedef void is_boost_scoped_enum_tag;
typedef int underlying_type;
copy_option() {}
explicit copy_option(underlying_type v) : v_(v) {}
underlying_type get_underlying_value_() const { return v_; }
private:
underlying_type v_;
typedef copy_option self_type;
public:
enum enum_type
{none=0, fail_if_exists = none, overwrite_if_exists};
enum_type get_native_value_() const { return enum_type(v_); }
operator enum_type() const { return get_native_value_(); }
friend bool operator ==(self_type lhs, self_type rhs) { return enum_type(lhs.v_)==enum_type(rhs.v_); }
friend bool operator ==(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)==rhs; }
friend bool operator ==(enum_type lhs, self_type rhs) { return lhs==enum_type(rhs.v_); }
friend bool operator !=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)!=enum_type(rhs.v_); }
friend bool operator !=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)!=rhs; }
friend bool operator !=(enum_type lhs, self_type rhs) { return lhs!=enum_type(rhs.v_); }
friend bool operator <(self_type lhs, self_type rhs) { return enum_type(lhs.v_)<enum_type(rhs.v_); }
friend bool operator <(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)<rhs; }
friend bool operator <(enum_type lhs, self_type rhs) { return lhs<enum_type(rhs.v_); }
friend bool operator <=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)<=enum_type(rhs.v_); }
friend bool operator <=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)<=rhs; }
friend bool operator <=(enum_type lhs, self_type rhs) { return lhs<=enum_type(rhs.v_); }
friend bool operator >(self_type lhs, self_type rhs) { return enum_type(lhs.v_)>enum_type(rhs.v_); }
friend bool operator >(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)>rhs; }
friend bool operator >(enum_type lhs, self_type rhs) { return lhs>enum_type(rhs.v_); }
friend bool operator >=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)>=enum_type(rhs.v_); }
friend bool operator >=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)>=rhs; }
friend bool operator >=(enum_type lhs, self_type rhs) { return lhs>=enum_type(rhs.v_); }
};
Note they have now made the C++03 type copy_option into a class mostly compatible with the enum type it encloses. Plus it in some cases acts more like a C++11 scoped enum: for example, if opt is a copy_option, you can't do opt==1. So you might want to consider doing just
boost::filesystem::copy_option myFunc();
instead. The biggest issue with that is that (because the old macros are used), the constructor of copy_option is explicit, so you must use direct-initialization and not copy-initialization to get from an enumerator value to a copy_option. That is, copy_option var = copy_option::fail_if_exists; and return copy_option::fail_if_exists; won't work, but copy_option var(copy_option::fail_if_exists); and return copy_option(copy_option::fail_if_exists); would.
In Boost 1.53.0 the involved Boost.Config macro changed from BOOST_NO_SCOPED_ENUMS to BOOST_NO_CXX11_SCOPED_ENUMS.
In Boost 1.56.0 the scoped enum support moved to Boost.Core, file boost/core/scoped_enum.hpp .

Does/would c++11/14 support something like vector<auto>

I am wondering if c++11/c++14 would/already support something like vector<auto>?
If not, Is there any reason?
It's not supported directly, and not immediately clear exactly what you want it to do.
Comments have already mentioned a couple of possibilities (such as Boost any and variant classes) for creating heterogeneous collections. I hope this isn't what you were after, because heterogeneous collections fit poorly with C++ so using them is ugly and clumsy. I suppose there are cases/situations where these really would be the best choices available, but at least in my experience, those cases are fairly rare.
Another possible interpretation of what you might want would be a vector that (like auto in general) holds exactly one type, but that type is deduced from the initializer, so if you initialized the vector from some ints, you'd get a vector<int>, and if you initialized it from some strings, you'd get a vector<string>, and so on. Although the language doesn't support that directly, it is pretty easy to simulate it to at least some degree. Template classes can't/don't ever deduce template parameters, but template functions do/can. Therefore, we can create a tiny function template to take some initializers, deduce their type, and return a vector of that type. For example:
template <class T>
std::vector<T> make_vector(std::initializer_list<T> init) {
return std::vector<T>(init);
}
This returns a vector<T> (with T deduced from the type of data in the initializer list), so you can do things like:
auto a = make_vector({ 1, 2, 3, 4 }); // a -> vector<int>
auto b = make_vector({ 1.0, 2.0, 3.0 }); // b -> vector<double>
auto c = make_vector({ "1"s, "2"s, "3"s }); // c -> vector<std::string>
That last one requires a user-defined literal operator that's new in C++14 (which many compilers don't yet support). The rest should be fine with C++11.
There has also been some discussion (and a proposal in N3602) of adding a capability (perhaps to C++17) where you'd be able to define something like the make_vector above, but as something like a templated constructor for the class. This would let you use argument deduction on the constructor to deduce the template parameter for the class as a whole, so you'd be able to do something like:
X x(1); // deduces as X<int>
X x(2.0) // deduces as X<double>
Warning though: this has been proposed but not accepted. It may (easily) never be accepted--and even if it is, it may be altered significantly before that happens.
No, not in C++11 or C++14, which are already finished and published.
But it's possible that vector<auto> and similar things like tuple<auto...> will be in C++17 as part of the Concepts work.
It follows quite naturally from the fact that std::vector<T> can be used in function templates and class template partial specializations where T is a template parameter, and also from the fact that polymorphic lambdas allow auto as a function parameter type (which is shorthand for a function template with deduced parameters).
The Concepts TS allows a "generic function" to be declared like:
auto func(auto arg);
Since you can have a function template like this:
template<typename T>
auto func(std::vector<T> v);
it makes sense to extend the generic function syntax to allow:
auto func(std::vector<auto> v);
and once you allow that in a function declaration, it should also be possible to allow it in variable declarations:
std::vector<auto> v = function_returning_vector_of_something();
The reason it isn't in C++11 is that auto was new, and it would have been too ambitious to try and make it do too much. In C++14 polymorphic lambdas were new, and again, expanding the uses of auto any further would have been ambitious.
For C++17 we have more experience with using auto in real code, and compiler writers are familiar with implementing it and know what is possible without too much effort.
A boost::any can store an instance of any type that can be copied, which is a lot of types.
In order to get the data out of your any, you have to know the exact type you stored in it.
Writing a simple any isn't hard:
#include <memory>
#include <utility>
struct any_internal {
virtual any_internal* clone() const = 0;
virtual ~any_internal() {};
};
template<class T>
struct any_details;
class any {
std::unique_ptr<any_internal> internal;
public:
any() = default;
any( any && ) = default;
any( any const&& o):any(o) {}
any( any & o ):any( const_cast<any const&>(o) ) {}
any& operator=( any && ) = default;
any& operator=( any const&& o ) { return this->operator=( o ); };
any& operator=( any & o ) { return this->operator=( const_cast<any const&>(o) ); };
any( any const& o ):internal( o.internal?o.internal->clone():nullptr ) {}
any& operator=( any const& o ) {
any tmp(o);
using std::swap;
swap( internal, tmp.internal );
return *this;
}
template<class U>
void reset( U&& o );
template<class U, class... Args>
void emplace( Args&&... args );
template<class U>
any( U&& o );
template<class U>
any& operator=(U&& o);
template<class T> T* get();
template<class T> T const* get() const;
template<class T> T* fast_get();
template<class T> T const* fast_get() const;
explicit operator bool() const { return internal!=nullptr; }
};
template<class T>
struct any_details : any_internal {
T t;
template<class...Args>
any_details( Args&&... args ):t(std::forward<Args>(args)...) {}
any_internal* clone() const override { return new any_details<T>{t}; }
};
template<class U, class... Args>
void any::emplace( Args&&... args ) {
internal.reset( new any_details<U>( std::forward<Args>(args)... ) );
}
template<class U>
void any::reset( U&& o ) {
emplace<typename std::decay<U>::type>( std::forward<U>(o) );
}
template<class U>
any::any( U&& o ) {
reset( std::forward<U>(o) );
}
template<class U>
any& any::operator=(U&& o) {
reset( std::forward<U>(o) );
return *this;
}
template<class T> T* any::get() {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::get() const {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T* any::fast_get() {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::fast_get() const {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
and a std::vector<any> behaves much like you might want a std::vector<auto> to do.
Increased efficiency can be achieved via small buffer optimizations (ie, store the T within the any if the t is small, instead of using the heap).
You'd probably also want to split get from fast_get, where get does a dynamic_cast and fast_get does a static_cast, again for efficiency. (When you know for certain, you can fast_get)
Basically this is a gussied up void*.

How to implement Scope Guard that restores value upon scope exit?

Would the following be an idiomatic C++11 implementation of a Scope Guard that restores a value upon scope exit?
template<typename T>
class ValueScopeGuard
{
public:
template<typename U>
ValueScopeGuard(T& value, U&& newValue):
_valuePtr(&value),
_oldValue(std::forward<U>(newValue))
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
~ValueScopeGuard()
{
if(_valuePtr)
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
}
// Copy
ValueScopeGuard(ValueScopeGuard const& other) = delete;
ValueScopeGuard& operator=(ValueScopeGuard const& other) = delete;
// Move
ValueScopeGuard(ValueScopeGuard&& other):
_valuePtr(nullptr)
{
swap(*this, other);
}
ValueScopeGuard& operator=(ValueScopeGuard&& other)
{
ValueScopeGuard(std::move(other)).swap(*this);
return *this;
}
private:
T* _valuePtr;
T _oldValue;
friend void swap(ValueScopeGuard& lhs, ValueScopeGuard& rhs)
{
using std::swap;
swap(lhs._valuePtr, rhs._valuePtr);
swap(lhs._oldValue, rhs._oldValue);
}
};
template<typename T, typename U>
ValueScopeGuard<T> makeValueScopeGuard(T& value, U&& newValue)
{
return {value, std::forward<U>(newValue)};
}
It could be used to temporarily change a value as follows:
int main(int argc, char* argv[])
{
// Value Type
int i = 0;
{
auto guard = makeValueScopeGuard(i, 1);
std::cout << i << std::endl; // 1
}
std::cout << i << std::endl; // 0
// Movable Type
std::unique_ptr<int> a{new int(0)};
{
auto guard = makeValueScopeGuard(a, std::unique_ptr<int>{new int(1)});
std::cout << *a << std::endl; // 1
}
std::cout << *a << std::endl; // 0
return 0;
}
Is a simple utility like this already implemented in a library somewhere? I had a look at Boost.ScopeExit, but its intended usage seems different and more complex.
Assuming makeValueScopeGuard to be implemented as :
template< typename T >
ValueScopeGuard<T> makeValueScopeGuard( T& t, T&& v )
{
return ValueScopeGuard<T>(t,std::move(v));
}
no, it is not very good implementation of scope guard, because it is going to fail when you pass l-values as the 2nd parameter :
int kk=1;
auto guard = makeValueScopeGuard(i, kk);
The second problem is that you used std::forward, when you should have used std::move.
As this question and answers show, people are usually using lambdas to implement scope guard.
Your move constructor leaves the pointer member uninitialized, so the rvalue object ends up holding a junk pointer, which it dereferences in its destructor. That's a bug. You should initialize it to nullptr and check for nullptr in the destructor.
For a type like this I would not expect move assignment to be a simple swap, I would expect the rvalue to end up not owning anything. So I would implement the move like this instead, so the rvalue ends up empty:
ValueScopeGuard& operator=(ValueScopeGuard&& other)
{
ValueScopeGuard(std::move(other)).swap(*this);
return *this;
}
The name makeValueScopeGuard isn't clear to me that it changes the value itself, I'd expect it to just copy the current value and restore it in the destructor.
As far as existing types go, the closest I can think of is the Boost I/O state savers, which do not alter the current state they just copy it and restore it.

C++11: using decltype on invalid expressions

Say I have a struct (in real life, that's an automaton):
struct automaton
{
bool get_final() const { return final; }
void set_final() { final = true; }
bool final = false;
};
for which I want to provide a view that sees it transposed (iow, reversed, or mirrored). Because I have more than just a single automaton class, I have a class template that wraps my automaton (I really want composition, not inheritance), and bounces all the function calls to the wrapped automaton, reversing what needs to be. For sake of simplicity, here, it just forwards the calls.
By hand, I'd get
template <typename Aut>
struct transposed_by_hand
{
Aut& aut;
auto get_final() const -> bool
{
return aut.get_final();
}
auto set_final() -> void
{
aut.set_final();
}
};
But there are many functions, and I don't want to hard-code so much information (the function signature) in the wrapper. Thanks to variadic templates and perfect forwarding for the incoming arguments, and decltype for the result, it's quite easy to have one macro to factor the definition of all the const member-functions, and another macro for non-const member functions (the difference being precisely the const). Basically, in this case it boils down to this:
template <typename Aut>
struct transposed_with_decltype
{
Aut& aut;
auto get_final() const -> decltype(aut.get_final())
{
return aut.get_final();
}
auto set_final() -> decltype(aut.set_final())
{
aut.set_final();
}
};
This works well for non-const automata, but breaks if I wrap a const automaton:
int main()
{
const automaton aut;
transposed_by_hand<const automaton> trh = { aut };
transposed_with_decltype<const automaton> trd = { aut };
}
My compilers complain that (G++ 4.9):
f.cc: In instantiation of 'struct transposed_with_decltype<const automaton>':
f.cc:44:49: required from here
f.cc:34:12: error: passing 'const automaton' as 'this' argument of 'void automaton::set_final()' discards qualifiers [-fpermissive]
auto set_final() -> decltype(aut.set_final())
^
and (Clang++ 3.3):
f.cc:42:23: error: default initialization of an object of const type 'const automaton' requires a user-provided default constructor
const automaton aut;
^
f.cc:34:36: error: member function 'set_final' not viable: 'this' argument has type 'const automaton', but function is not marked const
auto set_final() -> decltype(aut.set_final())
^~~
f.cc:44:49: note: in instantiation of template class 'transposed_with_decltype<const automaton>' requested here
transposed_with_decltype<const automaton> trd = { aut };
^
f.cc:6:12: note: 'set_final' declared here
void set_final() { final = true; }
^
2 errors generated.
And they are right! The expression in the decltype is breaking the const-ness of the wrapped automaton. Yet, I am not going to use this function, I swear. Just like I will not use the corresponding one wrapped by hand.
So my question is: is there a means to write the definition of the wrapping set_final so that I don't have to spell out its signature (input and output)? I have tried to use std::enable_if, but it changes nothing to the problem here. And anyway, it would need that the compiler be lazy, and accepts not to evaluate the second parameter of std::enable_if if it does not need to...
template <typename Aut>
struct transposed_with_decltype
{
Aut& aut;
auto get_final() const -> decltype(aut.get_final())
{
return aut.get_final();
}
auto set_final() -> typename std::enable_if<!std::is_const<Aut>::value,
decltype(aut.set_final())>::type
{
aut.set_final();
}
};
Thanks in advance.
I can get it to work (using GCC 4.6) just by using the advice Xeo mentions in his comment. That is, I turn the function into a trivial template, like so:
template<typename = void>
auto set_final() -> decltype(aut.set_final()) {
return aut.set_final();
}
== EDIT ==
Luc Danton comments below that a more recent GCC may reject the code, complaining that the decltype isn't dependent. I only have 4.6 here, but perhaps this could be worked around using something like this:
template<typename KLUDGE = int>
auto set_final() -> decltype((&aut+KLUDGE(0))->set_final()) {
return aut.set_final();
}
YMMV.

Resources