Рекурсивная распаковка пакета шаблонов для функции без параметров

Я пытаюсь создать шаблон структуры с пакетом типов вариативного шаблона, который может вычесть сумму размеров всех переданных типов.

Ниже вы найдете упрощенный пример, в реальном контексте вычисленный размер используется для создания дополнительных объектов-членов.

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

Я привык к этому рекурсивному подходу к распаковке параметров, когда дело доходит до списков аргументов, и предположил, что он также работает с функциями без аргументов и явной спецификацией шаблона. Однако я получаю следующую ошибку при компиляции с помощью clang

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

Таким образом, кажется, что последняя итерация рекурсии здесь не работает - не уверен, почему компилятор просто не выбрал наиболее очевидный выбор: тот, у которого есть только один тип шаблона - так же, как это произошло бы, если бы существовал фактический аргумент шаблона передается в функцию.

Итак, что мне нужно сделать, чтобы эта компиляция и работала должным образом?

1 ответ

Решение

Для C++14 вы можете использовать SFINAE:

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

этот шаблон будет рассматриваться только в том случае, если размер пакета параметров>= 1.

Демо

Другие вопросы по тегам