2016-03-07 13 views
8

Methods in C++ 14 può dire se si chiamano su un L-valore o un valore di R:Prevenire L-value esemplificazione in C++ 14

struct A{ 
    A() { puts("Ctor"); } 
    void m() const & { puts("L-value"); } 
    void m() const && { puts("R-value"); } 
}; 

int main(){ 
    A a; //Ctor 
    a.m() //L-value 
    A().m(); //Ctor; R-value 
} 

Può un ctor dire quale tipo sta costruendo? Posso disabilitare completamente la costruzione dei valori L dalla mia classe?

Ho una classe proxy (diversi, in realtà), che dovrebbe sempre convertire in qualcos'altro. Usarlo senza convertire è un errore. Posso rilevare questo errore in fase di runtime, ad esempio aggiungendo un membro #ifndef NDEBUG; e impostandolo nel cast specificato dall'utente, quindi eseguendo assert(used_) nella classe del proxy Dtor, tuttavia sarebbe molto meglio se potessi ottenere il compilatore per impedire instatiation di L-value istanze di tale delega, in primo luogo:

auto x = Proxy().method1().method2(); // no 
Proxy p; // no 
Target x = Proxy(); //yes 
Target x = Proxy().method1().method2(); //yes 

Posso fare qualcosa di simile con il C++ 14?

+6

Il modo vecchio di ottenere ciò che si desidera è impostare il costruttore su privato e consentire la costruzione solo tramite metodi statici. Penso che sarebbe anche più intuitivo per la persona che lavora con il tuo codice. – ypnos

+1

'auto && x = Proxy();' non può essere impedito IIRC. E poi 'x' è un proxy lvalue modificabile. – dyp

+0

Ho la sensazione che la risposta sia ancora no e tu devi fare quello che ypnos suggerisce – NathanOliver

risposta

2

Perché, naturalmente:

#include <iostream> 
using namespace std; 

class B; 

class A 
{ 
public: 
    A(B&& b) {} 

    A(const B&) = delete; 
}; 

class B {}; 

int main() 
{ 
    B b; 

    // A a1; <- error 
    // A a2 = b; // <- error 
    A a3 = move(b); // <- fine 

    return 0; 
} 
+0

Per quanto ho capito 'A a3 = move (b);' non dovrebbe compilare perché 'a3' è un lvalue. – nwp

+0

In questo caso lo snippet di codice non aiuta affatto, giusto – IceFire

+0

Grazie. Userò questo. È abbastanza vicino – PSkocik

3
struct temporary_only { 
    static temporary_only make() { return {}; } 
    temporary_only(temporary_only&&)=delete; 
    int get()&& { return 3; } 
private: 
    temporary_only() {} 
}; 

int main() { 
    //temporary_only x; // illegal 
    std::cout << temporary_only::make().get() << '\n'; // legal 
} 

live example.

Disattiviamo tutti i medici pubblici (inclusa copia/spostamento), quindi nessuno può creare un temporary_only eccetto tramite temporary_only::make (un valore massimo).

Nota che

temporary_only&& a = temporary_only::make(); 

funziona ancora. Qui abbiamo un rvalue associato a un riferimento di rvalue e quel riferimento di rvalue è esso stesso un lvalue con una durata di più righe (durata dell'ambito). Questo non può essere fermato.

+0

Anche 'const temporary_only & a = temporary_only :: make();' funziona pure – NathanOliver

+0

E per peggiorare le cose 'std :: move (a) .get()' funziona anche bene. – nwp