Построение временного вызова функции интерпретируется как объявление
В последнее время я столкнулся с проблемой, которая как-то (но только как-то) имеет для меня смысл. Он основан на интерпретации конструкции временного объекта как объявления единственного (!) Аргумента конструктора. Пожалуйста, посмотрите на минимальный пример ниже.
#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
с, таким образом, я явно о том, что я хочу.
Если необходимо использовать скобки {} только с одним изFoo
S, чтобы решить проблему ... почему строительствоbar3
потерпеть поражение?
Кроме того, x объявляется перед созданием любого бара. Почему компилятор не жалуется на это?
Последний вопрос связан с моей последней строкой примера кода. Короче говоря: что, по мнению компилятора, я хочу, чтобы он делал, и где я могу пропустить появление затенения?
PS: если интересно - использую gcc-4.9.2.
PPS: я попробовал то же самое сbar
конструктор брал триFoo0
в качестве аргументов. Та же история здесь. Но ошибка ничего не говорит о конфликтующей декларации, а о переопределенииx
.