13

Considering the following function :

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

What is the most simple thing to put instead of /* SOMETHING */ in order to return the sum of sizeof all arguments ?

For example myFunction(int, char, double) = 4+1+8 = 13

Vincent
  • 57,703
  • 61
  • 205
  • 388

6 Answers6

17

In C++17, use a fold expression:

template<typename... List> 
inline constexpr unsigned int myFunction(const List&... list)
{
    return (0 + ... + sizeof(List));
}
T.C.
  • 133,968
  • 17
  • 288
  • 421
16
unsigned myFunction() {return 0;}

template <typename Head, typename... Tail>
unsigned myFunction(const Head & head, const Tail &... tail) {
    return sizeof head + myFunction(tail...);
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Smart (+1) - with `inline` will be even smarter. – PiotrNycz Oct 01 '12 at 02:48
  • 2
    @PiotrNycz: `inline` as an optimization thing, is just a hint. Nothing more. Personally I value code clarity far more than that hinting, and then `inline` should better be reserved for its one guaranteed effect, namely its ODR effect. – Cheers and hth. - Alf Oct 01 '12 at 03:03
  • 8
    @PiotrNycz: Yes, if you need to define the non-template overload in a header file, then it will need to be `inline`. That's rather irrelevant to the question, though. – Mike Seymour Oct 01 '12 at 03:11
  • It works perfectly as a compile time `constexpr` in gcc, clang and VS12. I wonder why there's no standard library support for this. – ceztko Feb 28 '15 at 12:12
4

Based off of this comment and the following comments on the question, you could use this (note: completely untested)

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);
Community
  • 1
  • 1
JKor
  • 3,822
  • 3
  • 28
  • 36
  • 2
    This begs the interesting question: will this be statically computed (all the way down) ? – Matthieu M. Oct 01 '12 at 08:16
  • I do not think this will be statically computed unless someone made a constexpr version of std::accumulate, or if you happen to have a super optimizing compiler, but I have no idea about if any compiler will optimize that much. – JKor Oct 01 '12 at 20:42
  • unfortunately I don't have a version of Clang with `std::initializer_list` :/ – Matthieu M. Oct 02 '12 at 07:10
3

Two years late but an alternative solution guaranteed to be computed by the compiler (if you don't mind the different syntax):

template < typename ... Types >
struct SizeOf;

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

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

Used as constexpr std::size_t size = SizeOf<int, char, double>::Value; // 4 + 1 + 8 = 13

Pharap
  • 3,826
  • 5
  • 37
  • 51
0

Here's a template way:

#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;
}
-3

I've just found that :

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

But :

1) Do I have the guarantee that the result will always be the same on all compilers ?

2) Do the make_tuple will make and overhead at compile-time ?

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • 2
    This does not compute the sum of the sizes. You do have a guarantee that the size of the tuple is greater than or equal to the sum of the sizes. – Luc Danton Oct 01 '12 at 02:38
  • 2
    An implementation is allowed to do what they want. Perhaps more pragmatically, remember that the only guarantee on the size of something like `struct { int i; double j; };` is that it's at least `sizeof(int) + sizeof(double)`, but it can be larger. – Luc Danton Oct 01 '12 at 02:42
  • 3
    @Vincent - because of struct padding: http://stackoverflow.com/questions/5397447/struct-padding-in-c – PiotrNycz Oct 01 '12 at 02:43
  • 1
    @LucDanton Actually, not even that, if you have empty types. – T.C. Mar 18 '16 at 18:36