Ich habe mit auto
in herumgespielt std::pair
. Im folgenden Code soll die Funktion f
einen std::pair
Typ zurückgeben, der von einem Vorlagenparameter abhängt.
Ein Arbeitsbeispiel:
BEISPIEL 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
Dies funktioniert mit gcc 9.2, gcc 10.0, clang 9.0 und clang 10.0.
Als nächstes wollte ich den Rückgabetyp std::pair
aus Gründen der Übersichtlichkeit explizit schreiben :
BEISPIEL 2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
Sowohl gcc 9.2 / 10.0 als auch clang 9.0 / 10.0 konnten dies nicht kompilieren.
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
Nach der letzten Fehlermeldung scheint gcc 9.2 zu glauben, dass dies std::pair<auto, auto>
eine ist int
. Wie kann das erklärt werden?
gcc 10.0
error: returning initializer list
Dieser Fehler ist verständlich, ich habe jedoch erwartet, dass der Konstruktor von std::pair
aufgerufen wird, oder fehlt hier etwas?
klirren 9.0 und 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
Ok, Clang mag nichts davon. Aus der zweiten Fehlermeldung geht hervor, dass clang auch glaubt, dass der Rückgabetyp ist int
.
Um den beim Kompilieren mit gcc 10.0 erhaltenen Fehler zu beheben, habe ich mich entschlossen, std::pair
explizit Folgendes zurückzugeben:
BEISPIEL 3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
klirren 9.0 und 10.0
Wie zuvor, jedoch mit einem zusätzlichen:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
Hier denkt Clang immer noch, wir kehren zurück int
?
gcc 9.2
Das Gleiche wie vorher.
gcc 10.0
Es klappt!
Ich denke, einige Funktionen müssen noch implementiert werden, oder gibt es in einer der oben beschriebenen Situationen einen Compiler, der richtig und der andere falsch ist? Meiner Meinung nach sollte Beispiel 2 funktionieren. Oder sollte es nicht?
auto x = {1, 2};
funktioniert, aber nur wenn alle Typen gleich sind.int
. Es ist nicht so, dass diesint
ein Platzhalter in Fehlermeldungen ist. Der Compiler glaubt wirklich, dass es ein istint
. (Um dies klarer zu machen, hätte gcc wahrscheinlich irgendwann "int annehmen" sagen sollen.)std::pair __f{1,2};
funktioniert.std::optional f() { return 4; }
Arbeit haben wollen .