Possiedo un oggetto functor non strutturato che sto tentando di memorizzare come std::function
all'interno di un altro oggetto. Questo oggetto è davvero pesante, quindi è contrassegnato come non copiabile, ma ha un costruttore di mosse. Tuttavia, il tentativo di costruire una funzione std ::, o assegnarlo, da un costruttore temporaneo fallisce.Can std :: function può essere spostato dal riferimento rvalue a un oggetto temporaneo temporaneo?
Ecco un esempio minimo per provocare l'errore.
// pretend this is a really heavyweight functor that can't be copied.
struct ExampleTest
{
int x;
int operator()(void) const {return x*2;}
ExampleTest() :x(0){}
ExampleTest(int a) :x(a){}
// allow move
ExampleTest(ExampleTest &&other) :x(other.x) {};
private: // disallow copy, assignment
ExampleTest(const ExampleTest &other);
void operator=(const ExampleTest &other);
};
// this sometimes stores really big functors and other times stores tiny lambdas.
struct ExampleContainer
{
ExampleContainer(int);
std::function<int(void)> funct;
};
/******** ERROR:
Compiler error: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest'
******************/
ExampleContainer::ExampleContainer(int x)
: funct(ExampleTest(x))
{}
/******** ERROR:
Compiler error: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest'
******************/
int SetExample(ExampleContainer *container)
{
container->funct = ExampleTest();
return container->funct();
}
In una costruzione ancora più semplice, dove sto solo facendo una funzione locale, ho anche l'errore:
int ContrivedExample()
{
// extra parens to sidestep most vexing parse
std::function<int()> zug((ExampleTest()));
/*** ERROR: 'ExampleTest::ExampleTest' : cannot access private member
declared in class 'ExampleTest' */
int troz = zug() ;
return troz;
}
Per quanto posso dire, in tutti questi casi, un dovrebbe essere passato al costruttore di funzioni come valore di rvalue. Eppure il compilatore vuole copiarli.
Cosa dà? È possibile passare oggetti functor non copiabili (ma spostabili) su un costruttore std :: function? Ci sono soluzioni alternative con i puntatori e così via, ma voglio capire cosa sta succedendo qui.
Gli errori specifici riportati sopra provengono da Visual Studio 2012 con la patch CTP C++ 11. Anche GCC 4.8 e Clang 3 cadono, con i propri messaggi di errore.
Se si utilizza C++ 11, perché non utilizzare l'inizializzazione brace 'ExampleTest {}' e '= delete' invece di copy-ctor privato e assignment-op? – dyp
Cosa succede quando si aggiunge un operatore di assegnazione movimento? –
@DyP Nessuno dei compilatori a cui ho accesso può supportare in modo affidabile la costruzione dell'elenco inizializzatore o la sintassi '= delete'. – Crashworks