В последнее время я столкнулся с проблемой, которая каким-то образом (но только как-то) имеет смысл для меня. Он основан на интерпретации конструкции временного объявления как объявления единственного (!) Аргумента конструктора. Пожалуйста, ознакомьтесь с минимальным примером ниже.Построение временного вызова функции интерпретируется как объявление
#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
s не имеют стандартного конструктора. Поэтому не имеет смысла интерпретировать что-то вродеFoo0(x)
как объявлениеx
.Почему работает
bar1
иbar2
? Для меня очевидно, что работает конструкцияbar4
, так как я использую {} -бетоны для всех временныхFoo
s, поэтому я четко о том, что хочу.Если для решения проблемы необходимо использовать только {} -бетоны с одним из
Foo
s ... почему конструкцияbar3
не работает?Кроме того, x объявляется до того, как будет построена любая панель. Почему компилятор не жалуется на это?
Последний вопрос связан с моей последней строкой примера кода. Короче говоря: что компилятор думает, что я хочу, чтобы он это сделал, и где мне не хватает видимости тени?
PS: Если это интересно, я использую gcc-4.9.2.
PPS: Я пробовал то же самое с конструктором bar
с тремя аргументами Foo0
. Та же история здесь. Но ошибка ничего не говорит о противоречивой декларации, а о переопределении x
.
Как вы знаете, 'bar0' является объявлением функции, которая принимает три' Foo 'и возвращает' Foo', она сама по себе не является объектом 'Foo'. Кроме того, тот факт, что объявление 'bar3' не работает, является ошибкой в любом компиляторе, который вы используете. Эта строка должна работать так же, как в [clang] (http://coliru.stacked-crooked.com/a/d5f8305eff385830). – 0x499602D2
@ 0x499602D2 прослушивается для меня в g ++ 4.8.1 –
Верно: 'bar0' - это объявление функции, которая принимает три' Foo 'и возвращает' Bar'. – sedriel