1

Why is it that I can call a constructor directly, but when I use exactly the same arguments in emplace_back, I get an error "No matching member function for call to 'emplace_back'"? To get the error, I need to be passing a list to the constructor. There must be something very simple going on here, but I can't find it in a search.

Here is a minimal example.

class A {
public:
    A(std::list<double> c){
    }
};

void test(){
    A an_A = A({0.0});               //No error
    std::list<A> list_of_As;
    list_of_As.emplace_back({0.0});  //Error
}
Nathan Reading
  • 113
  • 1
  • 6

1 Answers1

2

The problem with {} is that it has several types it can describe. Now, when you don't specify the type, the compiler need to deduce which input type you ment to send, and it's unable to do that. For this reason you have to specify the type of the {}.

void test(){
    A an_A = A({0.0});
    std::list<A> list_of_As;
    list_of_As.emplace_back(list<double>{0.0});
}

Another options:

for the next class:

class A {
public:
    A(list<double> c, int a){
    }
};

You can use:

list_of_As.emplace_back(list<double>{0.0}, 1);
//list_of_As.emplace_back(A({0.0}, 1)); <-- Avoid using this. Explanation is right after this section.
list_of_As.emplace_back(initializer_list<double>{0.0}, 1);

Emplace Vs Push

is there any good reason not to solve the problem with A({0.0}) rather than list{0.0} ?

Yes. emplace_back used for creating the objects of the list in place instead of copy/move them later to the list. There is no reason for using emplace_back like it was push_back. The right way to use emplace_back is to send it the arguments of the object's constructor, and not the object itself.

push_back will move your object into the list/vector if only it moved by reference (rvalue) and if the element type has a move assignment operator.

For more reading about move/copy and push_back/emplace_back

Coral Kashri
  • 3,436
  • 2
  • 10
  • 22
  • 4
    While this code may solve the problem the answer would be a lot better with an explanation on how/why it does. Remember that your answer is not just for the user that asked the question but also for all the other people that find it. – NathanOliver Jul 20 '18 at 13:29
  • You right, I will add an explanation. – Coral Kashri Jul 20 '18 at 14:14
  • Before the edit, this answer just used: list_of_As.emplace_back(A({0.0})); That seemed nicely simple, and worked (also in my actual project). The edit helps me understand better why what I had tried didn't work. But is there any good reason not to solve the problem with A({0.0}) rather than list{0.0} ? – Nathan Reading Jul 20 '18 at 17:44
  • 1
    @NathanReading I added a new section to answer your new question. – Coral Kashri Jul 20 '18 at 19:47