2016-10-28 3 views
1

Ich mag angeben, so etwas tun:anderen Datentyp zurück, ohne explizit Datentyp

template<class T> 
T foo(uint8_t x) 
{ 
    if (x<32) return ((int32_t)1<<x); 
    else return ((int64_t)1<<x); 
} 

aber ich will nicht foo<int32_t>(x) oder foo<int64_t>(x) nennen. Es sieht einfach nicht gut aus. Ich möchte, dass der Rückgabetyp automatisch korrekt abgeleitet wird.

Beabsichtigte Verwendungsbeispiele:

std::max(foo(10),some_variable); // return type of foo need to match some_variable 
std::min(foo(32),another_variable); 

Die Lösung muss Vorlage nicht sein. Wenn Makros dasselbe erreichen können, verwende ich gerne Makros. Irgendwelche Vorschläge?

+1

Ist 'foo ()' möglich? (Ich meine ist "x" eine Laufzeit oder Kompilierzeit Wert?) – Jarod42

+0

es ist ein Laufzeit-Wert – james

+0

Leider ist es nicht möglich, wie Sie es verwenden. Wenn 'T' auch für ein Argument verwendet wurde, würde es gut funktionieren. –

Antwort

4

Der Rückgabetyp einer Funktion (auch eine Template-Funktion) — in der Tat, jeder Ausdruck, wenn ich mich nicht irre, das ist warum Gills Antwort nichts löst — ist ein Kompilierzeitattribut. Was Sie in Ihrem Code wollen, ist eine Laufzeitentscheidung. Dies ist ein fundamentaler Konflikt, der nicht direkt lösbar ist (selbst ein Typdef würde den Widerspruch nicht lösen, afaics).

Was Sie können tun, ist eine Art von Griff oder Container. Zum Beispiel können Sie immer nur eine 64-Bit-Ganzzahl zurückgeben, die gewissermaßen ein Basistyp für die kürzeren Spezialisierungen ist (d. H. Sie können immer eine kurze Ganzzahl in eine 64-Bit-Ganzzahl umwandeln, aber nicht unbedingt umgekehrt).

Sie könnten auch etwas komplizierter programmieren (große num-Klasse, polymorphe Klasse, was auch immer), aber das Wesentliche wäre das gleiche: Der Rückgabetyp wäre eine Kompilierzeit, und der Typ könnte irgendwie alles speichern Mögliche Werte und einige Laufzeit Informationen darüber, was "Typ" es tatsächlich ist (wenn alle Werte Integer sind, ist die Laufzeit Informationen der Wert selbst), und möglicherweise mit stark typisierten Konvertierungsmethoden kommen.

1

Die Lösung muss keine Vorlage sein. Wenn Makros das selbe erreichen können, bin ich glücklich, Makros zu verwenden.

Ja, aber das macht es nicht irgendein sauber mehr als explizit Foo erklärt, welche Vorlagentyp Sie wollen.

Wie auch immer, diese can be done aber es ist ziemlich nicht:

#include <iostream> 
#include <stdint.h> 

#define FOO(x) (x < 32 ? Foo_32(x) : Foo_64(x)) 

int32_t Foo_32(uint8_t x) 
{ 
    std::cout << "32\n"; 
    return (int32_t)1<<x; 
} 

int64_t Foo_64(uint8_t x) 
{ 
    std::cout << "64\n"; 
    return (int64_t)1<<x; 
} 

int main() { 
    FOO(35); 
    FOO(22); 
    return 0; 
} 
+1

Ich denke, der Typ der ternären Ausdruck ist immer "int64_t", was ich denke nicht, was das OP will. Wie bei Funktionen wird der Typ des Ausdrucks zur Kompilierungszeit bestimmt, und der kleinere Int wird befördert. Nebenbei, du sollst deine Makros halten. –

+0

@ PeterA.Schneider Guter Punkt. –

+0

@ PeterA.Schneider warum würdest du es immer int64_t sagen? –