2012-10-01 33 views

Odpowiedz

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) - z 'inline' będzie jeszcze mądrzejszy. – PiotrNycz

+2

@PiotrNycz: 'inline' jako rzecz optymalizacji, to tylko podpowiedź. Nic więcej. Osobiście cenię czytelność kodu znacznie więcej niż to podpowiedź, a następnie 'inline' powinien być lepiej zarezerwowany dla jednego gwarantowanego efektu, mianowicie jego efektu ODR. –

+7

@PiotrNycz: Tak, jeśli potrzebujesz zdefiniować przeciążenie bez szablonu w pliku nagłówkowym, to musi to być 'inline'. To raczej nie ma znaczenia dla pytania. –

4

oparciu off this comment i następujące komentarze na pytanie, można użyć tego (uwaga: całkowicie niesprawdzone)

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

To nasuwa interesujące pytanie: czy zostanie to statycznie obliczone (do samego końca)? –

+0

Nie sądzę, że zostanie to obliczone statycznie, chyba że ktoś stworzył constexpr wersję std :: akumulować, lub jeśli masz super kompilator optymalizujący, ale nie mam pojęcia, czy jakikolwiek kompilator zoptymalizuje tak dużo. – JKor

+0

Niestety nie mam wersji Clang z 'std :: initializer_list':/ –

-2

Właśnie stwierdził, że:

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

Ale:

1) Czy mam gwarancję, że wynik będzie zawsze taki sam we wszystkich kompilatorach?

2) Czy make_tuple będzie robił i napełniał podczas kompilacji?

+2

Nie oblicza to sumy rozmiarów. Masz gwarancję, że rozmiar krotki jest większy lub równy sumie rozmiarów. –

+0

Jak może być większy? – Vincent

+1

Implementacja może robić, co chce. Być może bardziej pragmatycznie, pamiętaj, że jedyna gwarancja na rozmiar czegoś takiego jak 'struct {int i; podwójne j; }; 'jest to co najmniej' sizeof (int) + sizeof (double) ', ale może być większy. –

2

Dwa lata późno jednak alternatywne rozwiązanie gwarantuje być obliczane przez kompilator (jeśli nie przeszkadza innej składni):

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); 
}; 

Używany jako const int size = SizeOf<int, char, double>::Value; // 4 + 1 + 8 = 13

5

w C++ 17, używać krotny wyrażenie:

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

Oto sposób szablon:

#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; 
} 
Powiązane problemy