2012-10-01 8 views
6

die folgende Funktion Betrachtet:sizeof variadische Vorlage (Summe aus sizeof aller Elemente)

template<typename... List> 
inline unsigned int myFunction(const List&... list) 
{ 
    return /* SOMETHING */; 
} 

Was ist die einfachste Sache, statt /* SOMETHING */ in Ordnung zu bringen, die Summe von sizeof alle Argumente zurück?

Zum Beispiel myFunction(int, char, double) = 4+1+8 = 13

Antwort

13
unsigned myFunction() {return 0;} 

template <typename Head, typename... Tail> 
unsigned myFunction(const Head & head, const Tail &... tail) { 
    return sizeof head + myFunction(tail...); 
} 
+0

Smart (+1) - mit 'Inline' wird noch schlauer. – PiotrNycz

+2

@PiotrNycz: 'Inline' als eine Optimierung Sache, ist nur ein Hinweis. Nichts mehr. Persönlich schätze ich Code-Klarheit weit mehr als das Hinting, und dann sollte 'inline' besser für seinen einen garantierten Effekt reserviert werden, nämlich seinen ODR-Effekt. –

+7

@PiotrNycz: Ja, wenn Sie die Nicht-Template-Überladung in einer Header-Datei definieren müssen, dann muss sie "inline" sein. Das ist für die Frage allerdings ziemlich irrelevant. –

4

Basierend off von this comment und die folgenden Ausführungen auf die Frage, können Sie diese (Anmerkung: völlig ungetestet) verwenden

std::initializer_list<std::size_t> sizeList = {sizeof(List)...}; //sizeList should be std::initializer_list, according to the comments I linked to 
return std::accumulate(sizeList.begin(), sizeList.end(), 0); 
+0

Dies wirft die interessante Frage auf: Wird dies statisch berechnet (ganz unten)? –

+0

Ich glaube nicht, dass dies statisch berechnet wird, es sei denn, jemand hat eine consExpr-Version von std :: accumic erstellt, oder wenn Sie einen superoptimierenden Compiler haben, aber ich habe keine Ahnung, ob ein Compiler so viel optimiert. – JKor

+0

leider habe ich keine Version von Clang mit 'std :: initializer_list':/ –

-2

ich nur, dass gefunden habe:

template<typename... List> 
inline unsigned int myFunction(const List&... list) 
{ 
    return sizeof(std::make_tuple(list...)); 
} 

Aber:

1) Habe ich die Garantie, dass das Ergebnis bei allen Compilern immer gleich ist?

2) Wird make_tuple zur Kompilierzeit einen Overhead erzeugen?

+2

Dies berechnet nicht die Summe der Größen. Sie haben eine Garantie, dass die Größe des Tupels größer oder gleich der Summe der Größen ist. –

+0

Wie kann es größer sein? – Vincent

+1

Eine Implementierung darf tun, was sie wollen. Denken Sie vielleicht pragmatischer daran, dass die einzige Garantie für die Größe von etwas wie "struct {int i; Doppel j; }; 'ist, dass es mindestens' sizeof (int) + sizeof (double) 'ist, aber es kann größer sein. –

2

Zwei Jahre zu spät, aber eine alternative Lösung durch die Compiler berechnet werden garantiert (wenn Sie nicht über die andere Syntax beachten):

template < typename ... Types > 
struct SizeOf; 

template < typename TFirst > 
struct SizeOf <TFirst> 
{ 
    static const auto Value = (sizeof(TFirst)); 
}; 

template < typename TFirst, typename ... TRemaining > 
struct SizeOf < TFirst, TRemaining ... > 
{ 
    static const auto Value = (sizeof(TFirst) + SizeOf<TRemaining...>::Value); 
}; 

als const int size = SizeOf<int, char, double>::Value; // 4 + 1 + 8 = 13

5

In C++ 17 gebraucht, verwenden, um eine Falte Ausdruck:

template<typename... List> 
inline constexpr unsigned int myFunction(const List&... list) 
{ 
    return (0 + ... + sizeof(List)); 
} 
0

Hier ist eine Vorlage Art und Weise:

#include <iostream> 

template<typename T, typename ...Ts> 
class PPackSizeOf 
{ 
    public: 
    static const unsigned int size = sizeof(T) + PPackSizeOf<Ts...>::size; 
}; 


template<typename T> 
class PPackSizeOf<T> 
{ 
    public: 
    static const unsigned int size = sizeof(T); 
}; 

template<typename ...Ts> 
class FixedSizeBlock 
{ 
    private: 
     char block[PPackSizeOf<Ts...>::size]; 
    public: 

}; 

int main() 
{ 
    FixedSizeBlock<char,long> b; 
    std::cout << sizeof(b) << std::endl; 
    return 0; 
}