Ultimamente mi sono imbattuto in un problema che in qualche modo (ma solo in qualche modo) ha senso per me. Si basa sull'interpretazione della costruzione di un temporaneo come dichiarazione del singolo argomento del costruttore (!). Si prega di dare un'occhiata all'esempio minimo qui sotto.La costruzione di una chiamata di funzione temporanea viene interpretata come dichiarazione
#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.
}
ho già letto che espressioni come:
Foo(a);
sono interpretati (se v'è un costruttore standard) come dichiarazione di a. Questo ha senso ed è assolutamente soddisfacente, dal momento che puoi semplicemente usare le {} -bracks per rendere esplicita la costruzione. Ma quello che non capisco è:
Perché c'è un problema con la costruzione di bar0? Tutti i
Foo
s non hanno un costruttore standard. Quindi non ha senso interpretare qualcosa comeFoo0(x)
come dichiarazione dix
.Perché la costruzione di
bar1
ebar2
funziona? Per me è ovvio che la costruzione dibar4
funziona, dal momento che utilizzo le {} -bracks per tutti i valori temporaneiFoo
s, quindi sono esplicito su ciò che voglio.Se è necessario utilizzare solo il {} -brackets con una sola delle
Foo
s per risolvere il problema ... perché la costruzione dibar3
fallire?Inoltre, x viene dichiarato prima che venga creata qualsiasi barra. Perché il compilatore non si lamenta di ciò?
L'ultima domanda è relativa alla mia ultima riga di codice di esempio. Per farla breve: cosa pensa il compilatore che voglio che faccia e dove mi manca l'apparenza di shadowing?
PS: Se è interessante, utilizzo gcc-4.9.2.
PPS: Ho provato lo stesso con il costruttore bar
prendendo tre argomenti come Foo0
s. Stessa storia qui. Ma l'errore non dice nulla sulla dichiarazione in conflitto ma sulla ridefinizione di x
.
Proprio così, sapete, 'bar0' è la dichiarazione di una funzione che accetta tre' Foo's e restituisce un 'Foo', non è esso stesso un oggetto' Foo'. Inoltre, il fatto che la dichiarazione di 'bar3' non funzioni è un bug in qualunque compilatore stai usando. Quella linea dovrebbe funzionare come fa in [clang] (http://coliru.stacked-crooked.com/a/d5f8305eff385830). – 0x499602D2
@ 0x499602D2 bugged per me in g ++ 4.8.1 –
Giusto per essere corretto: 'bar0' è la dichiarazione di una funzione che accetta tre' Foo's e restituisce una 'Barra'. – sedriel