2011-07-08 9 views
9

boost :: funkcja FAQ item 3 specjalnie rozwiązuje scenariusz Jestem zainteresowany:Czy funkcja tr1 :: function połknąć może wartości zwracane?

Dlaczego istnieją obejścia dla pustych zwrotów? C++ pozwala im! Void powraca są dozwolone przez standard C++, jak w tym fragmencie kodu:

void f(); 
void g() { return f(); } 

Jest to ważny wykorzystanie podwyższając :: bo nieważne powraca nie są używane. Z pustych deklaracji, chcielibyśmy próbuje skompilować źle sformułowane kodu podobnego do:

int f(); 
void g() { return f(); } 

w istocie, nie używając void powraca pozwala boost :: funkcja połknąć wartość powrotną. Jest to zgodne z , umożliwiając użytkownikowi przypisanie i wywołanie funkcji i obiektów funkcji z parametrami, które nie są dokładnie zgodne z .

Niestety, to nie działa w VS2008:

int Foo(); 
std::tr1::function<void()> Bar = Foo; 

ta produkuje błędów zaczynając:

c:\Program Files\Microsoft Visual Studio 9.0\VC\include\xxcallfun(7) : error C2562: 'std::tr1::_Callable_fun<_Ty>::_ApplyX' : 'void' function returning a value 

Czy jest to wadą wykonania VS2008 TR1? Czy to działa w VS2010? Czy TR1 spełnia tę funkcję? A co z C++ 0x?

+0

VS2010 podaje ten sam błąd. – Xeo

+2

'void g() {return f(); } 'jest dozwolone do obsługi kodu szablonu, gdzie typ powrotu funkcji może nie być znany z góry ... nadal jest to błąd dla' f() ', aby rzeczywiście zwrócić wartość, jeśli' g() 'nie. Biorąc to pod uwagę, nie zdziwiłbym się stwierdzeniem, że komitet ds. Standardów zdecydował się odejść od wdrożenia Boost w tym zakresie, ponieważ zapewnia bardziej intuicyjne zachowanie. Ale ponieważ gcc * nie pozwala na takie zachowanie, nie jestem pozytywny. –

Odpowiedz

8

Wierzę, że tr1 rozwiązuje ten problem. N1836 (Najnowsza wersja TR1) mówi:

obiekt funkcji F typu F jest niepokryta typów argumentów, T1, T2, ... tn typu powrotnym R, jeżeli ze względu lwartościami t1 , t2, ..., tNoftypesT1, T2, ..., TN, odpowiednio, INVOKE (f, t1, t2, ..., tN) jest dobrze uformowane ([3.3]), a jeśli R jest nie nieważne, cabrio do R.

W przykładzie R jest nieważne, i tak ostatnia część wymogów dla Callable (wymienialnej R) jest ignorować re.

Wygląda jednak na to, że C++ 0x (C++ 11) zmienia reguły. W C++ 11 Callable jest zdefiniowane jako INVOKE(f, t1, t2, ..., tN, R), które jest zdefiniowane w [wymaganiach funkcji] jako wymagające, aby INVOKE(f, t1, t2, ..., tN) było niejawnie wymienialne na R, bez wyjątku, gdy R jest nieważne. Więc w C++ 11 Twój przykład powinien zawieść.

+2

Czy wiesz, czy istnieje uzasadnienie dla tej zmiany/regresji? Jeśli nie, to brzmi jak wada. –

+0

To naprawdę brzmi dziwnie. Żadne wyrażenie nie jest domyślnie przekształcalne w 'void'.Nawet wyrażenie typu "void" (zgodnie z klauzulą ​​4 pkt 3). Trzeba wyraźnej obsady, aby przekształcić rzeczy w "pustkę". Przypuszczam, że intencją jest to, że tylko jeśli typ wyniku jest inny niż "R", to wyrażenie jest niejawnie konwertowane na 'R'. Wtedy wynik może nadal mieć typ "void", gdy 'R' jest' void'. Łatwo ich jednak oszukać, IMO :) –

Powiązane problemy