Как мне заставить мой sizeof sum struct работать с пустым пакетом параметров - PullRequest
8 голосов
/ 14 февраля 2020

У меня есть эта variadi c структура для определения суммы размера всех передаваемых типов:

template <typename U, typename... T> struct TotalSizeOf 
    : std::integral_constant<size_t, sizeof(U) + TotalSizeOf<T...>::value> {};

template <typename U> struct TotalSizeOf<U> 
    : std::integral_constant<size_t, sizeof(U)> {};

Использование: TotalSizeOf<double, int, char>::value

Вопрос в том, как сделать Я изменяю это, чтобы позволить ему работать с пустым пакетом параметров, чтобы он возвращал 0;

например TotalSizeOf<>::value

В настоящее время я получаю ошибку error: wrong number of template arguments (0, should be at least 1)

У меня есть только C ++ 14.

Ответы [ 2 ]

12 голосов
/ 14 февраля 2020

Вы просто должны специализироваться также на <>

Пример:

template < typename... T> struct TotalSizeOf;

template < typename U, typename... T> struct TotalSizeOf<U, T...>
: std::integral_constant<size_t, sizeof(U) + TotalSizeOf<T...>::value> {};

template <> struct TotalSizeOf<> :
std::integral_constant<size_t, 0 > { };

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}
5 голосов
/ 14 февраля 2020

С C ++ 17 вы можете получить это без сложного метапрограммирования шаблона, используя выражения сгиба:

#include <iostream>
#include <type_traits>

template<class... T> 
struct TotalSizeOf: std::integral_constant<std::size_t, (0 + ... + sizeof(T))> {};

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}

Это также должно быть более эффективным при компиляции (конечно, во время выполнения, это то же самое).

PS: Просто прочитайте, что у вас есть только C ++ 14, но вы оставите это здесь, так как я думаю, что приятно видеть, что мы менее вынуждены делать неловкий TMP в новых версиях C ++.

Приложение: Менее элегантно, чем C ++ 17, но C ++ 14 и практически без tmp

#include <iostream>
#include <type_traits>
#include <initializer_list>

constexpr size_t sum(std::initializer_list<size_t> arr) {
    // Accumulate is sadly not constexpr in C++14
    auto ret = 0ul;
    for(auto i: arr) {
        ret += i;
    }
    return ret;
}

template<class... T> 
struct TotalSizeOf: std::integral_constant<std::size_t, sum({sizeof(T)...})> {};

int main()
{
    std::cout << TotalSizeOf< int, char>::value << std::endl;
    std::cout << TotalSizeOf< char>::value << std::endl;
    std::cout << TotalSizeOf< >::value << std::endl;
}
...