0

I'm trying to create a struct template with a variadic template type pack, that can deduct the sum of the size of all types passed in.

Below you find a simplified example, in the real-world context, the size computed is used to create further member objects.

template <typename... Types>
struct OverallSize
{
    template <typename FirstType, typename... NextTypes>
    static constexpr size_t sizesum() { return sizeof (FirstType) + sizesum<NextTypes...>(); }
    template <typename LastType>
    static constexpr size_t sizesum() { return sizeof (LastType); }

    static constexpr size_t size = sizesum<Types...>();
};

// Should work e.g. like this
auto s = OverallSize<int, float, char>::size; // s will be 9 on x86-64

I'm used to this recursive parameter unpacking approach when it comes to argument lists and assumed this works as well with argument-less functions and explicit template specification. However I get the following error when compiling with clang

Call to 'sizesum' is ambiguous
...
Candidate function [with FirstType = unsigned long, NextTypes = <>]
Candidate function [with LastType = unsigned long]

So it seems as if the last recursion iteration doesn't work here – not sure why the compiler doesn't simply chose the most obvious choice: The one with only one template type – just as it would happen if there was an actual template argument passed to the function.

So, what do I have to do to make this compile and work as desired?

PluginPenguin
  • 1,576
  • 11
  • 25

1 Answers1

1

For C++14 you can use SFINAE:

template <
    typename FirstType, 
    typename... NextTypes, 
    std::enable_if_t<sizeof...(NextTypes) >= 1>* = nullptr >
static constexpr size_t sizesum() {
    return sizeof (FirstType) + sizesum<NextTypes...>(); 
}

this template will be considered only if parameters pack has size >= 1.

Demo

rafix07
  • 20,001
  • 3
  • 20
  • 33