static_assert размер каждого параметра в пакете параметров

Я пытаюсь проверить, можно ли сохранить каждый параметр в пакете параметров в пределах 8 байт (sizeof <= 8)

У меня есть функция подписи:

template <typename Return, typename... Arguments>
inline auto invoke(std::uint64_t hash, Arguments... arguments) -> Return

Используя выражения сгиба, я попытался:

static_assert((sizeof(arguments) <= 8 && ...));

Который не удалось скомпилировать с unexpected token '...', expected 'expression' - Я полагаю, это неверно или неправильно?

Используя концепции и ограничения C++20, я предполагаю, что что-то подобное возможно?

template <typename Return, typename... Arguments> requires (sizeof(arguments) <= 8 || ...)
inline auto invoke(std::uint64_t hash, Arguments... arguments) -> Return

Я предполагаю, что есть способ использовать стандартную библиотеку, чтобы проверить, что тип вписывается в std::uint64_t сказать тоже?

2 ответа

С концепциями C++20 есть много способов достичь желаемого поведения. Например:

template <typename T, size_t N>
concept bool SizeLessEqual = sizeof(T) <= N;

template <SizeLessEqual<8>... Types>
void f() { }

int main() {
    f<bool, char, int, double>();
    f<std::string>();  // error
}

Демонстрационная версия: https://wandbox.org/permlink/Q9tifNVplsx9BjGN

Другой вариант - ваше решение:

template <typename... Types> requires ((sizeof(Types) <= 8) && ...) 
void f() { }

Или, например:

template <typename... Types> requires (std::max({ sizeof(Types)... }) <= 8) 
void f() { }

Попробуйте так:

#include <cstdint>
#include <utility>
template <typename... Arguments>
auto invoke(std::uint64_t hash, Arguments... arguments)
{
    auto check = []( auto&& argument )
    {
        static_assert( sizeof(argument) <= 8, "size too large" );
        return 0;
    };
    auto dummy = { 0, ( check(std::forward<Arguments>(arguments)), 0) ... };
    return 0;
}

int main()
{
    invoke( 0UL, '1' );
    invoke( 0UL, '1', 2 );
    invoke( 0UL, '1', 2, 3UL );
    //invoke( 0UL, '1', 2, 3UL, static_cast<long double>(1.0) );
    return 0;
}

Использование оператора запятой и initializer_list, чтобы сделать трюк.

С C++17 мы можем дополнительно урезать код до:

template <typename... Arguments>
auto invoke(std::uint64_t hash, Arguments... arguments)
{
    auto check = []( auto&& argument )
    {
        static_assert( sizeof(argument) <= 8, "size too large" );
    };
    (check(std::forward<Arguments>(arguments)), ...);
}

пользуясь выражениями сгиба.


Я не понимаю отрицательных голосов, но так как это мой последний пост в stackru, я загрузил живой пример на wandbox: https://wandbox.org/permlink/NZbqpRaTs2TFOCwG

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