2015-01-24 20 views
10

ja zaskoczeni, widząc, że po kompilacji:typu mającego konwersję do typu && operatora

struct C { 
    operator C&&() { 
     std::cerr << "ref'd\n"; 
     throw std::runtime_error("what is happening?"); 
    } 
}; 

typu z operatorem na własnej przemiany RValue-odniesienia. Jednak nie mogę zmusić operatora do wywołania tego, co myślę, że może to zrobić. Przekazywanie wartości do funkcji pobierającej wartość rvalue kończy się niepowodzeniem, a wywołanie std::move obiektu nie wywołuje niczego.

Dlaczego ten kod jest w stanie skompilować się w ogóle i czy istnieje sposób, aby uruchomić tę funkcję?

clang daje warning: conversion function converting 'C' to itself will never be used z lub bez odniesienia do typu.

+0

Ten sam wynik na klang dla operatora 'C &()'. Pytania oznaczają. –

+1

Nie jest technicznie nieopłacalne; możesz zrobić 'C c; c.operator C &&(); 'lub weź wskaźnik funkcji członka' C && (C :: * ptr)() = & C :: operator C &&; 'i użyj go. Po prostu nie będzie używane w zdalnie rozsądnym kodzie. – Wintermute

+0

@Wintermute Innym wyjątkiem jest wysyłka wirtualna. –

Odpowiedz

12
struct C 
{ 
    operator C() 
    { 
    } 
}; 

jest również dozwolone i daje takie samo ostrzeżenie. To, o których mowa w §12.3.2/1:

Funkcja konwersji nie służy do konwersji (ewentualnie CV-kwalifikowana) obiektu do (ewentualnie) cv wykwalifikowany samego typu obiektu (lub odniesienie do tego), do (prawdopodobnie kwalifikowanej z cv) klasy bazowej z tego typu (lub odniesienia do niego) lub do (ewentualnie kwalifikowanego cv) nieważne.

Innymi słowy, nie jest zabronione, ale po prostu nie robi nic. Yakk i Wintermute już przedstawiono przykłady funkcji element składni połączenie, ale cppreference przedstawia przykład wirtualnego wysłania które omówiono w przypisie 116 (N3337, przypis 118 N4140)

struct D; 
struct B { 
    virtual operator D() = 0; 
}; 
struct D : B 
{ 
    operator D() override { return D(); } 
}; 

int main() 
{ 
    D obj; 
    D obj2 = obj; // does not call D::operator D() 
    B& br = obj; 
    D obj3 = br; // calls D::operator D() through virtual dispatch 
} 
+0

Czy jest coś bardziej bezużytecznego w standardzie, zastanawiam się ... – Deduplicator

+0

Drobna nitpick: To przypis 116, a nie 118. – Wintermute

+0

@Deduplicator Myślę, że przedłużenie okresu życia tymczasowego, jeśli jest powiązane z odniesieniem do const, jest całkiem bezużyteczne. – BWG

3
void foo(C&&){} 
int main(){ 
    C c; 
    foo(c.operator C&&()); 
} 

więc zasadniczo bezużyteczne , ale nie do końca.

Powiązane problemy