2011-08-10 12 views
15

Niedawno zawarłem mój umysł wokół pojęć C++ 0x glvalue, xvalues ​​i prvalues, a także referencje rvalue. Jest jednak jedna rzecz, która wciąż mnie wymyka:Co to jest referencja rwartości do typu funkcji?

Co to jest "wartość odniesienia rubl do typu funkcji"? Jest dosłownie wspomniany wiele razy w wersjach. Dlaczego wprowadzono taką koncepcję? Jakie są tego zastosowania?

+0

czy w końcu zrozumiałeś odpowiedź? Pozostawiłem komentarz pod odpowiedzią, więc jeśli znasz wyjaśnienie, podaj je. dzięki –

Odpowiedz

15

nienawidzę być okrągły, ale odniesienia RValue funkcjonować t ype jest referencją rwartości do typu funkcji. Istnieje coś takiego jak typ funkcji, np. void(). I możesz utworzyć odniesienie rwartości do niego.

Pod względem systemu klasyfikacji wprowadzonego przez N3055, jest to wartość x.

Jego zastosowania są rzadkie i niejasne, ale nie są bezużyteczne. Rozważmy na przykład:

void f() {} 
... 
auto x = std::ref(f); 

x ma typ:

std::reference_wrapper<void()> 

A jeśli spojrzeć na streszczeniu dla reference_wrapper obejmuje:

reference_wrapper(T&) noexcept; 
reference_wrapper(T&&) = delete; // do not bind to temporary objects 

W tym przykładzie T jest typem funkcja void() . Tak więc druga deklaracja tworzy wartość rinue dla typu funkcji, aby zapewnić, że reference_wrapper nie może zostać skonstruowany z argumentem rwartości. Nawet jeśli T jest const.

Jeśli nie było prawnym utworzenie wartości rwartej dla funkcji, ochrona ta spowodowałaby błąd czasu kompilacji, nawet jeśli nie przekazaliśmy do konstruktora wartości r.

+3

Myślę, że miałeś na myśli 'void()'. 'void()()' było błędnym demolowaniem GCC/binutils, ale [zostało ustalone jakiś czas temu] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46332). –

+1

@Johannes: Dzięki! To było * najbardziej * pomocne! –

+0

To jest przerażające i mam problemy ze zrozumieniem. O ostatnim zdaniu dotyczącym błędu czasu kompilacji - czy SFINAE nie spowodowałoby w takim przypadku zignorowania drugiej deklaracji? – Kos

0

W starym standard C++, co następuje jest zabronione:

int foo(); 
void bar(int& value); 

int main() 
{ 
    bar(foo()); 
} 

ponieważ typ powrót foo() jest RValue i przepuszcza się przez odniesienie do pręta().

to pozwolono choć z włączonymi w rozszerzeniach Microsoft Visual C++ od (chyba) 2005.

możliwe obejścia bez C++ 0x (lub MSVC) byłoby deklarujących

void bar(const int& value); 

lub przy użyciu temp regulowaną przechowywania zwrotnego wartość foo() i przechodzącej zmiennej (jako punkt odniesienia) do pręta():

int main() 
{ 
    int temp = foo(); 
    bar(temp); 
} 
+5

Być może źle zrozumiałem pytanie, ale myślę, że OP mówi o wartościach rvalues ​​odniesienie do typów funkcji (np. lambdas i tak dalej). – user786653