Предисловие. Я пытаюсь получить более глубокое понимание метапрограммирования шаблонов C++, и кажется, что я застрял ... Я пишу библиотеку, которую мы будем использовать для сериализации двоичных данных [de]. Ожидаемая структура распакованных данных известна в определенной степени, и мне представляется разумным использовать эти знания для: (1) проверки данных (2) пропускать нерелевантные части и (3) распаковывать данные непосредственно в структуры, известные во время компиляции - как избежать ненужного копирования, так и сделать код клиента более чистым.Реализация статической версии std :: all_of с использованием метапрограммирования шаблонов?
Так, например, я хочу реализовать функцию, которая распаковывает массив (массивы могут содержать гетерогенные данные, например, в JSON). Для простоты предположим, что массив имеет фиксированный размер и не имеет гнездования.
Реальная проблема Я хочу, чтобы написать функцию, которая будет принимать входной буфер, содержащий данные, преобразованные в последовательную форму (или поток - это не имеет значения, в нашем контексте) и std::tuple
, содержащий lvalues для вывода (пакет параметров - худшая альтернатива, потому что мне придется иметь дело с гнездом в конце концов). Поэтому мне сначала нужно проверить, подходят ли все типы в кортеже для распаковщика и дать соответствующее сообщение об ошибке, если они не являются.
Так что код что-то вроде:
template<typename T>
struct is_integral_lvalue : std::integral_constant<bool,
std::is_lvalue_reference<T>::value &&
std::is_integral<T>::value &&
(sizeof(T) == 4 || sizeof(T) == 8)>
{
};
/* ... */
template<typename TInputBuffer, typename... TDest>
static TRet unpack_int_tuple(TInputBuffer src_buf, std::tuple<TDest...> &&dest) noexcept(is_noexcept)
{
static_assert(typelist::all_are<is_integral_lvalue, TDest...>::value,
"All types in a tuple must be integral lvalue-references");
/* do unpacking */
}
условия, is_integral_constant
может быть несколько произвольно. Поэтому желательно, чтобы шаблон all_are
мог использовать любой унарный предикат. Возникает вопрос: что я должен писать в typelist::all_are
(и, может быть, что мне следует исправить в приведенном выше коде, чтобы можно было написать такой all_are
)?
Рабочий пример был бы идеальным, конечно, но я буду признателен за общие идеи/советы, если они будут полезны.
Ограничения Моя цель - не только реализовать эту функцию, но и понять, как она работает (такое решение, как «просто использовать boost :: mpl» или «boost :: hana», не подходит). Чем меньше несвязанных вещей мы используем, тем лучше. Предпочтительно код должен быть в C++ 11 (мы еще не готовы использовать C++ 1y/GCC 4.9). Я также надеюсь, что можно избежать использования макросов препроцессора.
Некоторые вещи, которые я googled. Boost.MPL, конечно, может быть использован, но он большой, он использует медленные рекурсивные шаблоны (вместо variadics), и трудно понять, что «под капотом». Boost :: hana, к сожалению, основан на полиморфных лямбдах, которые не попадали в C++ 11. Я видел эту библиотеку https://github.com/Manu343726/Turbo, но кажется, что для ее использования требуется слишком много изменений в коде (чтобы обернуть почти все типы в своих адаптерах). Он также использует такие вещи, как ленивая оценка (при расширении шаблонов) - здесь это не нужно, и код будет намного сложнее читать.
Эта библиотека https://github.com/ldionne/mpl11 является почти что мне нужно. Проблема опять же связана с обертками: and_
реализован как особый случай metafunction foldr
(который разворачивается для лучшей производительности во время компиляции). И все они используют использование метафлора, ленивость и т. Д., Что делает его очень трудным для понимания (за исключением, может быть, для опытных программистов на функциональном языке). Так что для меня было бы достаточно объяснения, как пропустить все эти очень обобщенные и сложные методы и написать тот же шаблон and_
, но более простым способом (для более конкретного использования).
Рад видеть, что кто-то думает об использовании моей библиотеки, даже если ее окончательно отклонили. Большое спасибо :) – Manu343726