3

den folgenden Code vor:Rückgabetyp eines Anruf nur mit Angaben zu Art und nicht auf Objekte

template <class F, class... Args> 
void function(F&& f, Args&&... args) 
{ 
    using type1 = decltype(std::forward<F>(f)(std::forwards<Args>(args)...)); 
    using type2 = decltype(/*equivalent expression but only using types */); 
} 

Gibt es eine Möglichkeit type2 die gleichen wie type1 in allen Fällen zu machen, aber nur die Typen in der Verwendung decltype Ausdruck, oder mit anderen Worten nur mit F und Args und nicht f und args?

+10

Ich bin mir nicht sicher, ob ich die Frage verstehe. Fragen Sie nach ['std :: declval'] (http://en.cppreference.com/w/cpp/utility/declval)? –

+0

Warum willst du 'f' und' args' nicht verwenden? Nur neugierig. – Rakete1111

+0

@ Rakete1111: das ist kein x/y Problem, es ist nur, dass in den letzten paar Jahren, während ich Template metaprogramming code geschrieben habe, habe ich mir diese Frage mehrmals gestellt, und nicht sicher, was die Antwort war (denn immer noch nach 6 Jahren mit ihnen spielen, nicht sicher, all die subtilties für universelle Referenzen und std :: forward zu verstehen. – Vincent

Antwort

6

Sie erreichen dies nur mit C++ 11 und ohne decltype mit std::result_of:

using type2 = typename std::result_of<F&&(Args&&...)>::type; 

Example in compiler explorer.

Sobald Sie beginnen, C++ 17 zu verwenden, sollten Sie std::result_of durch std::invoke_result ersetzen, wie in der documentation beschrieben.

+2

Beachten Sie, dass [' std :: result_of'] (http://en.cppreference.com/w/cpp/types/result_of) ist jetzt veraltet (seit C++ 17). Von C++ 17 sollten Sie ['std :: invoke_result'] (http://en.cppreference.com/w/cpp/types/result_of) verwenden – WhiZTiM

+0

Guter Punkt, habe ich die Antwort entsprechend bearbeitet. – jupp0r

3

Vielleicht ist die Lösung, die Sie declval verwenden wollen, ist dies:

template <class F, class... Args> 
void function(F&& f, Args&&... args) 
{ 
    using type1 = decltype(std::forward<F>(f)(std::forward<Args>(args)...)); 
    using type2 = decltype(std::forward<F>(declval<F>())(std::forward<Args>(declval<Args>())...)); 
} 

this helps

1

beginnen mit diesem:

decltype(std::forward<F>(f)(std::forwards<Args>(args)...)); 

Änderung dieser:

decltype(std::declval<F>()(std::declval<Args>()...)); 

und getan. std::declval<T>() ist eine Funktion ohne Implementierung, die denselben Rückgabetyp wie std::forward hat.

hat std::result_of (und hat std::result_of_t), aber das hat ein paar kleine Macken, die sie unvollkommen machen. Sie können diese Macken durch die Verwendung von && beheben:

std::result_of_t< F&&(Args&&...) > 

In sie invoke_result hinzugefügt diese Macken zu beheben:

std::invoke_result_t< F, Args... > 

die Macken sind, weil die Typen in einem Funktionsaufruf Signatur zulässig sind nicht alle Typen , und die Sprache stellt sie im Hintergrund auf bestimmte Weise ein (entfernt die oberste Ebene const, lässt nicht zu, dass einige Typen zurückgegeben werden usw.).

Verwandte Themen