3

I have a class A defined like bellow:

class A
{
public:
   A() = default;

   explicit A(uint32_t a, uint32_t b)
   {
      std::cout << "construct" << std::endl;
   }

   A(const A& obj)
   {
      std::cout << "copy" << std::endl;
      *this = obj;
   }

   A(const A&& obj)
   {
      std::cout << "move" << std::endl;
      *this = obj;
   }

   A& operator=(const A& obj)
   {
      std::cout << "copy operator" << std::endl;
      return *this;
   }

   A& operator=(const A&& obj)
   {
      std::cout << "move operator" << std::endl;
   }
};

I use the class like this:

std::vector<std::pair<A, bool>> v;
v.emplace_back(A(0, 1), true);

The emplace_back has the following output:

construct
move
copy operator

My question is, is there any way to construct A of the pair in-place without calling the move and copy operator?

Cricket
  • 491
  • 1
  • 7
  • 16
  • Same question for map: [c++ - How can you emplace directly a mapped value into an unordered_map? - Stack Overflow](https://stackoverflow.com/questions/68828864/how-can-you-emplace-directly-a-mapped-value-into-an-unordered-map) – user202729 Aug 18 '21 at 08:48

1 Answers1

6

Yes, std::pair has this constructor:

cppreference/utility/pair/pair

template< class... Args1, class... Args2 >
pair( std::piecewise_construct_t,
      std::tuple<Args1...> first_args,
      std::tuple<Args2...> second_args );

Forwards the elements of first_args to the constructor of first and forwards the elements of second_args to the constructor of second. This is the only non-default constructor that can be used to create a pair of non-copyable non-movable types.

You can therefore invoke:

std::vector<std::pair<A, bool>> v;
v.emplace_back(std::piecewise_construct, 
               std::make_tuple(0, 1), 
               std::make_tuple(true));
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • Nice! That solved my problem. I saw that in the example of cppreference **std::forward_as_tuple** has been used, does it make any difference with **std::make_tuple** in this case? – Cricket Apr 25 '19 at 07:55
  • 1
    `std::make_tuple` always creates a tuple owning its contents. `std::forward_as_tuple` creates a tuple of references. In your particular case it doesn't matter as we're dealing with primitive types. – Vittorio Romeo Apr 25 '19 at 13:46