Move constructor is not called when using boost::pool_allocator - c++

I have the following simple test code.
#include <stack>
#include <iostream>
#include "boost/pool/pool_alloc.hpp"
struct Frame
{
uint32_t i{};
Frame(uint32_t _i) : i(_i) {}
Frame(const Frame& f)
{
std::cout << "Copy constructor" << std::endl;
i = f.i;
}
Frame(Frame&& f)
{
std::cout << "Move constructor" << std::endl;
std::swap(i, f.i);
}
};
int main(int argc, char* argv[])
{
{
std::stack<Frame, std::deque<Frame>> stack;
Frame f(0);
stack.push(std::move(f)); // Move constructor
stack.push(Frame(1)); // Move constructor
}
{
std::stack<Frame, std::deque<Frame, boost::pool_allocator<Frame>>> stack;
Frame f(0);
stack.push(std::move(f)); // Copy constructor
stack.push(Frame(1)); // Copy constructor
}
return 0;
}
When I compile this code with either Clang or GCC, it gives me the following output:
Move constructor
Move constructor
Copy constructor
Copy constructor
Why does using boost::pool_allocator prevent the compiler from using the move constructor?
Am I missing something?

pool_allocator does not perfect forward the arguments to construct: It simply takes a const reference to the value type and passes that on as the initializer for placement new.
That is because pool_allocator has not been updated for C++11 yet.

Related

Move only type adapting std::any with dummy copy constructor is safe?

I'd like to initialize std::any with a move only type variable. I found Cannot move std::any.
Compile error case
Before I use shared_ptr workaround from the linked answer, I tested the following code:
#include <utility>
#include <iostream>
#include <any>
struct move_only {
move_only() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
move_only(move_only const&) = delete;
move_only(move_only &&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main() {
move_only m;
std::any a(std::move(m)); // error. copy constructor is required
}
https://wandbox.org/permlink/h6HOSdgOnQYg4a6K
The code above outputs compile error because of move_only doesn't have copy constructor.
Add copy constructor for test
I added copy constructor for test.
#include <utility>
#include <iostream>
#include <any>
struct move_only {
move_only() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
move_only(move_only const&) {
// not called
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
move_only(move_only &&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main() {
move_only m;
std::any a(std::move(m)); // success but copy constructor is not called
}
https://wandbox.org/permlink/kxEnIslmVnJNRSn6
Then compile successfully finished as I expected. And I got interesting output.
move_only::move_only()
move_only::move_only(move_only &&)
It seems that the copy constructor isn't called. It is surprising for me.
And I come up with the following wrapper approach.
Add dummy copy constructor wrapper
#include <utility>
#include <iostream>
#include <any>
struct move_only {
move_only() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
move_only(move_only const&) = delete;
move_only(move_only &&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct wrapped_move_only : move_only {
wrapped_move_only(move_only&& m):move_only(std::move(m)) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
wrapped_move_only(wrapped_move_only const&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
assert(false);
}
wrapped_move_only(wrapped_move_only &&) = default;
};
int main() {
move_only m;
wrapped_move_only wmo(std::move(m));
std::any a(std::move(wmo));
}
https://wandbox.org/permlink/EDhq3KPWKP9fCA9v
The copy constructor of move_only is deleted. The class wapped_move_only inherits move_only and added copy constructor.
It successfully compiled and I got the following result.
move_only::move_only()
move_only::move_only(move_only &&)
wrapped_move_only::wrapped_move_only(move_only &&)
move_only::move_only(move_only &&)
It seems that I initialized std::any with move only type using the wrapper that provides dummy copy constructor. It is more efficient to use shared_ptr if the goal is just initialize std::any with move only type. It is expected behavior for me.
As long as I do move operation only for std::any once move_only is moved to std::any, is this code safe?
If std::any is copied, then assetion failed due to copy constructor of wrapped_move_only is called. I want to know move only case's safety.
I am also not sure why std::any's target requires copy constructor but it is not called.
templatized
If it is safe, I can improve this approach using template. The template add_dummy_copy_constructor is a kind of adaptor.
#include <utility>
#include <iostream>
#include <any>
struct move_only {
move_only() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
move_only(move_only const&) = delete;
move_only(move_only &&) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
template <typename T>
struct add_dummy_copy_constructor : T {
add_dummy_copy_constructor(T&& t):T(std::move(t)) {}
add_dummy_copy_constructor(add_dummy_copy_constructor const&) {
assert(false);
}
add_dummy_copy_constructor(add_dummy_copy_constructor &&) = default;
};
int main() {
move_only m;
std::any a(add_dummy_copy_constructor(std::move(m)));
}
https://wandbox.org/permlink/guEWPIrK9wiJ3BgW
I am also not sure why std::any's target requires copy constructor but it is not called.
The design of std::any is to be one concrete type that can hold any copyable type. When you copy a std::any, you copy whatever it is it's holding underneath
The std::any needs to know how to copy the underlying object regardless of if it is ever actually going to be copied (how would it know whether or not this happens?). So it must be a compile error if the underlying type isn't copy-constructible.
However, when we're constructing the std::any itself, at that point we know the concrete object we're constructing from. And if that concrete object happens to be an rvalue, then we can just move-construct std::any's underlying object from the constructor parameter rather than copy-constructing. It's a free win there.
None of your code actually copies a std::any, so none of it would invoke std::any's copy constructor which would invoke the underlying types copy constructor.
A similar thing happens with std::function and maybe it would be more obvious what the difference here is. When I construct a std::function<void()>, there is the static requirement that the object be invokable with no arguments. It is a compile error if it is not invokabe.
But simply constructing the std::function<void()> will not actually invoke the underlying function - those are separate operations. You wouldn't expect this assertion to trigger:
std::function<void()> f = []{ assert(false); }

Using boost move with an instance parameter

I have a function that deals with a movable-only instance that is a wrapper around something else. That object provides means of access to the wrapped object and some checks which require it to be non-copyable. (Use case is a table of values, where the dtor of the wrapper should assert that all values were were accessed)
I defined a custom ctor from the wrapped type and implemented the move ctor/assignment.
However I'm getting an error due to an attempted copy: error: 'Movable::Movable(Movable&)' is private within this context
It works fine in C++11 but I need portability to C++03. How can I do this without an explicit instantiation of the wrapper and moving it into the function?
MWE:
#include <boost/move/move.hpp>
#include <iostream>
class Movable{
BOOST_MOVABLE_BUT_NOT_COPYABLE(Movable)
public:
int i;
Movable(int j):i(j){}
Movable(BOOST_RV_REF(Movable) other) // Move constructor
: i(boost::move(other.i))
{}
Movable& operator=(BOOST_RV_REF(Movable) other) // Move assignment
{
if(this != &other)
i = boost::move(other.i);
return *this;
}
};
void bar(Movable mov){
mov.i = 22;
std::cout << mov.i;
}
int main(int argc, char* argv[])
{
bar(5);
return 0;
}
The problem appears to be that the implicit conversion constructor interferes with the copy-constructor suppression.
Either use
Movable m(5);
bar(boost::move(m));
Or
bar(Movable(5));
To make sure that you select for the explicit constructor. Obviously, that means you can even mark it explicit:
Live On Coliru
#include <boost/move/move.hpp>
#include <iostream>
class Movable{
BOOST_MOVABLE_BUT_NOT_COPYABLE(Movable)
public:
int i;
explicit Movable(int j):i(j){}
Movable(BOOST_RV_REF(Movable) other) // Move constructor
: i(boost::move(other.i))
{}
Movable& operator=(BOOST_RV_REF(Movable) other) // Move assignment
{
if(this != &other)
i = boost::move(other.i);
return *this;
}
};
void bar(Movable mov){
std::cout << mov.i << " ";
mov.i = 22;
std::cout << mov.i << "\n";
}
int main() {
Movable m(5);
bar(boost::move(m));
bar(Movable(6));
}
Prints
5 22
6 22

Trying to use c++ move constructor...and fail

Right when I thought I understood what std::move and move constructors do, I tried to write some unit test, actually testing the move constructor for some class...
To my surprise I found, that I cannot think of a way to construct code which actually calls the move constructor. Worse, I cannot even set a breakpoint in the body of the move constructor (in VS2013 community edition, debug, 64bit build).
Wondering if this is a compiler peculiarity, I knocked up some small test code on my freebsd virtual machine, using clang (3.4.1). There, too I fail to find a way to get that move constructor invoked.
#include <iostream>
#include <stdint.h>
#include <string>
#include <algorithm>
#include <functional>
#include <ctype.h>
#include <locale>
void InPlaceToUpper( std::string& target )
{
std::transform(target.begin(), target.end(), target.begin(), ::toupper);
}
void InPlaceToLower( std::string& target )
{
std::transform(target.begin(), target.end(), target.begin(), ::tolower);
}
std::string ToUpper( const std::string& s )
{
std::string result;
result.resize(s.length());
std::transform(s.begin(), s.end(), result.begin(), ::toupper);
return result;
}
std::string ToLower( const std::string& s)
{
std::string result;
result.resize(s.length());
std::transform(s.begin(), s.end(), result.begin(), ::tolower);
return result;
}
class CFoo
{
std::string m_value;
public:
CFoo()
: m_value()
{
std::cout << "CFoo() called." << std::endl;
}
CFoo(const char *value)
: m_value(value)
{
std::cout << "CFoo(const char *) called." << std::endl;
}
CFoo(const std::string& value )
: m_value(value)
{
std::cout << "CFoo(const std::string&) called." << std::endl;
}
CFoo(const CFoo& other )
: m_value(other.m_value)
{
std::cout << "CFoo() copy constructor called." << std::endl;
}
CFoo(CFoo&& other )
: m_value(std::move(other.m_value))
{
std::cout << "CFoo() move constructor called." << std::endl;
std::cout << "other.m_value = " << other.m_value.c_str() << std::endl;
}
~CFoo()
{
std::cout << "~CFoo() called." << std::endl;
}
const CFoo& operator=( const CFoo& other )
{
std::cout << "CFoo copy assignment operator called." << std::endl;
if( &other != this )
{
m_value = other.m_value;
}
return *this;
}
const CFoo& operator=( CFoo&& other )
{
std::cout << "CFoo move assignment operator called." << std::endl;
if( &other != this )
{
m_value = std::move(other.m_value);
}
return *this;
}
CFoo ToUpper()
{
return CFoo(::ToUpper(m_value));
}
CFoo ToLower()
{
return CFoo(::ToLower(m_value));
}
const char * ToString() const
{
return m_value.c_str();
}
};
int main( int argc, const char *argv[] )
{
{
CFoo foo;
CFoo foo1("Hello World");
CFoo foo2 = CFoo("Hello again World!");
CFoo foo3(CFoo("Bye world"));
CFoo foo4 = CFoo("Bye again world");
CFoo foo5 = foo4.ToUpper();
CFoo foo6 = foo4.ToLower();
foo6 = foo4.ToUpper();
std::cout << "foo4: " << foo4.ToString() << std::endl;
foo6 = CFoo("Well well well");
}
return 0;
}
My apologies if the code is not as short as it might possibly be. But there are only a few spots to look at, namely my efforts to get the move constructor invoked in main() and the definition of the various constructors in class Foo.
I am aware of compiler settings which allow turning off RVO and stuff but for the purpose of using the feature "move constructor" in performance aware code, there should be a classic example of when it gets invoked. If that is not the case, I will probably decide not to even bother using move constructors at all.
To answer the question, you can tell me a line I can write in main() which gets the move constructor of CFoo called. Or you can tell me what I am doing wrong.
Does std::string support being moved like that? Maybe this is why my efforts fail?
Thanks, in advance.
In all your attempts to use the move constructor it is being elided, so that e.g. CFoo foo = CFoo(blah); is simply equivalent to CFoo foo(blah); which doesn't need to use the move constructor. This is a Good Thing because the compiler is optimising away the need for any copy or move to happen at all.
To see the move constructor being used try:
CFoo f1;
CFoo f2 = std::move(f1);
This constructs f2 from an rvalue, and nothing can be elided, so the move constructor will be used.
First of all, there is an error in std::string ToUpper(const std::string& s), namely there is no space in result. C++ algorithms do not grow their target containers automatically. You must either allocate space yourself, or use a inserter adaptor.
To make space in out, e.g. do this:
result.resize(s.length());
After it the move assignment operator called for:
foo6 = foo4.ToUpper();
foo6 = CFoo("Well well well");
The move constructor is called whenever an object is initialized from xvalue of the same type, which includes:
initialization, T a = std::move(b); or T a(std::move(b));, where b is of type T
function argument passing: f(std::move(a));, where a is of type T and f is void f(T t)
function return: return a; inside a function such as T f(), where a is of type T which has a move constructor.
For more see move constructors on cppreference.com.

Uniform initialization syntax difference

What's the difference between doing
A a{ A() };
and,
A a( A{} );
to avoid the Most Vexing Parse? When should I use a particular one?
The two syntaxes are equivalent in most situations, and which one to choose is mostly a matter of taste. If you are into uniform initialization, I would suggest doing:
A a{ A{} };
Otherwise, parentheses alone can be used to disambiguate:
A a((A())); // This can't be parsed as a function declaration
Notice, that there is one situation (very unlikely, I must say) where the two forms shown in your question are not equivalent. If your class A has a constructor that takes an initializer_list<A>, that constructor will be favored over the copy constructor when the braces are used:
#include <initializer_list>
#include <iostream>
struct A
{
A() { }
A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; }
A(A const& a) { std::cout << "copy-ctor" << std::endl; }
};
int main()
{
A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed)
A b{A()}; // Prints "init-list"
}
The above difference is shown in this live example.
In most situations they are equivalent, but A a{ A() }; will prefer a std::initializer_list constructor if one is present, while A a( A{} ); will prefer a move/copy constructor.
When the construct ends up calling a move/copy constructor, the construction of the new object can be elided, but this is not possible for a std::initializer_list constructor.
Neither syntax will ever be parsed as a function declaration, so both avoid the most-vexing-parse.
#include <iostream>
#include <initializer_list>
struct A {
A() {
std::cout << "A()\n";
}
A(A&&) {
std::cout << "A(A&&)\n";
}
A(std::initializer_list<A>) {
std::cout << "A(std::initializer_list<A>)\n";
}
};
int main()
{
{A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n"
{A a( A{} );} // Prints "A()\n" and *possibly*
// (depending on copy elision) "A(A&&)\n"
}

No call to the copy constructor

Consider this:
#include <iostream>
struct A{
A(){
std::cout << "Create empty A" << std::endl;
}
A(const A& a){
// Why is this never called??
std::cout << "Never called" << std::endl;
}
};
A genA() {
A a;
return a;
}
int main(int argc, const char *argv[])
{
A a(genA()); // Expected to call copy constructor
return 0;
}
Why is the copy constructor not called?
What should I do if I want to ensure that "Never called" is printed on the screen every time I copy A.
This is called as Return value optimization.
Compiler can optimize your code so that it bulds the object directly in the location where it would have been copied too. Thus there will be no reason to use the copy constructor.
Note: The standard explicitly allows it do so.
One way you can force the compiler to avoid RVO is to not return by value - e.g.
#include <iostream>
#include <memory>
struct A{
A() {
std::cout << "Create empty A" << std::endl;
}
A(const A& a) {
// This will be called now
std::cout << "Never called" << std::endl;
}
};
std::auto_ptr<A> genA() {
return std::auto_ptr<A>(new A);
}
int main(int argc, const char *argv[])
{
A a(*(genA().get())); // this will trigger the copy-ctor
return 0;
}
Though this is a horrible hack. I would instead ask why you want to do this? and if you are hoping to put some side-effects into the constructor, urge you to think otherwise.
Copy constructor invocations can be elided (even if they contain side effects), the standard allows that ([12.2]).
EDIT:
I suggest that you do not try to fight it in real world code.
If you just want to see the copy ctor executed in some example/turorial code, then it usually helps not to compile with optimization. Some compilers even have switches that help to avoid that. For GCC it should be -fno-elide-constructors.