Почему braced-init-list ведет себя по-разному при вызове функции по сравнению с вызовом конструктора?

Компиляция следующего кода с использованием clang 3.5.0 и gcc 4.9.1 выдает ошибку при последнем утверждении.

#include <iostream>

struct Foo { Foo(int x, int y) { std::cout << "Foo(int = " << x << ", int = " << y << ")" << std::endl; } };

void bar(int x, int y) { std::cout << "bar(int = " << x << ", int = " << y << ")" << std::endl; }

int main()
{
Foo({}, {});   // Foo(int = 0, int = 0)
Foo({1}, {2}); // Foo(int = 1, int = 2)
Foo({1, 2});   // Foo(int = 1, int = 2)

bar({}, {});   // bar(int = 0, int = 0)
bar({1}, {2}); // bar(int = 1, int = 2)
bar({1, 2});   // error: no matching function for call to 'bar'  <<< Why? <<<
}

Почему Foo({1, 2}) хорошо пока bar({1, 2}) не является?

В частности, было бы здорово узнать об обосновании.

5

Решение

Foo({1,2}) создает временный объект Foo и вызывает конструктор копирования.

Посмотрите этот модифицированный пример с конструктором копирования delete:
http://coliru.stacked-crooked.com/a/6cb80746a8479799

Это ошибки с:

main.cpp:6:5: note: candidate constructor has been explicitly deleted
Foo(const Foo& f) = delete;
6

Другие решения

Линия

bar({1, 2});

на самом деле проходит в bar функция, временный объект типа

<brace-enclosed initializer list> // it's made clear in the comments that brace initializers have no type

и нет никакого способа преобразовать этот временный объект в тип первого аргумента, который является int, Таким образом ошибка

не может конвертировать <brace-enclosed initializer list> в int для аргумента 1 в

void bar(int, int)
1

По вопросам рекламы [email protected]