Построение временного вызова функции интерпретируется как объявление

В последнее время я столкнулся с проблемой, которая как-то (но только как-то) имеет для меня смысл. Он основан на интерпретации конструкции временного объекта как объявления единственного (!) Аргумента конструктора. Пожалуйста, посмотрите на минимальный пример ниже.

#include <iostream>

class Foo0{
public:
  Foo0(int a){};
  void doStuff() {std::cout<<"maap"<<std::endl;};
};

class Foo1{
public:
  Foo1(int a){};
  void doStuff() {std::cout<<"maap"<<std::endl;};
};

class Foo2{
public:
  Foo2(int a){};
  void doStuff() {std::cout<<"maap"<<std::endl;};
};

class Bar{
public:
  Bar(Foo0 foo0, Foo1 foo1, Foo2 foo2){};
};

int main () {
  int x = 1;

  Bar bar0(Foo0(x), Foo1(x), Foo2(x)); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’; conflicting declaration ‘Foo2 x’ previous declaration as ‘Foo0 x’
  Bar bar1(Foo0{x}, Foo1(x), Foo2(x)); // Works WTF
  Bar bar2(Foo0(x), Foo1{x}, Foo2(x)); // Works WTF
  Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
  Bar bar4(Foo0{x}, Foo1{x}, Foo2{x}); // Works totally makes sens to me

  x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious though.
}

Я уже читал, что такие выражения, как:

Foo(a);

Интерпретируются (если есть стандартный конструктор) как объявление. Это имеет смысл, и это совершенно нормально, так как вы можете просто использовать скобки {}, чтобы сделать конструкцию явной. Но то, что я не понимаю, это:

Почему существует проблема со строительством bar0? ВсеFooУ них нет стандартного конструктора. Так что нет смысла истолковывать что-то вродеFoo0(x) как декларацияx.

Почему строительствоbar1 а такжеbar2 Работа? Для меня очевидно, что строительствоbar4 работает, так как я использую скобки {} для всех временныхFooс, таким образом, я явно о том, что я хочу.

Если необходимо использовать скобки {} только с одним изFooS, чтобы решить проблему ... почему строительствоbar3 потерпеть поражение?

Кроме того, x объявляется перед созданием любого бара. Почему компилятор не жалуется на это?

Последний вопрос связан с моей последней строкой примера кода. Короче говоря: что, по мнению компилятора, я хочу, чтобы он делал, и где я могу пропустить появление затенения?

PS: если интересно - использую gcc-4.9.2.
PPS: я попробовал то же самое сbarконструктор брал триFoo0в качестве аргументов. Та же история здесь. Но ошибка ничего не говорит о конфликтующей декларации, а о переопределенииx.

Ответы на вопрос(2)

Ваш ответ на вопрос