Add consstexpr TupleConverter::Size() when possible

master
Pawel Kurowski 2020-07-18 22:26:36 +02:00
parent 40400f3a5d
commit 2e28901b32
2 changed files with 84 additions and 11 deletions

View File

@ -292,14 +292,70 @@ namespace FSecure
template <typename T>
struct TupleConverter
{
/// @brief Use it to read from ByteView to tuple of types deduced from TupleTransform.
/// This is a helper method used to create dedicated logic of type reading after all data was retrieved form view as tuple.
/// @param bv. Buffer with serialized data.
/// @return tuple of retrieved data for type construction.
static auto ReadTuple(ByteView& bv)
private:
/// @brief Helper class compatible with Utils::Apply. Checks if size after serialization, of all tuple types, can be determined at compile time.
struct IsSizeConstexpr
{
return bv.Read<decltype(ByteConverter<T>::TupleTransform(std::declval<T>()))>();
template <typename ...Ts>
static constexpr auto Apply()
{
return ((ConverterDeduction<Ts>::FunctionSize::value == ConverterDeduction<Ts>::FunctionSize::compileTime) && ...);
}
};
/// @brief Helper class compatible with Utils::Apply. Determines size after serialization, of all tuple types.
struct GetConstexprSize
{
template <typename ...Ts>
static constexpr auto Apply()
{
return ((ByteConverter<Ts>::Size() + ...));
}
};
public:
/// @brief Type of helper tuple returned by ByteConverter<C>::TupleTransform.
/// @note This type will be deduced late in instantiation procedure.
/// @tparam C Type To be serialized.
template <typename C>
using TupleTransformType = decltype(ByteConverter<C>::TupleTransform(std::declval<C>()));
// MSVC is using late deduction of default template parameter type, and only if they are used.
// This allows definition of constexpr version of Size function using SFINAE.
// There are proposals implement same delay in clang, but it is not available yet, or possibly will never be.
#if defined (__clang__)
/// @brief Default implementation of Size method.
/// @param obj Object for serialization.
/// @return size_t. Number of bytes used after serialization.
static size_t Size([[maybe_unused]] T const& obj)
{
if constexpr (Utils::Apply<IsSizeConstexpr, TupleTransformType<T>>::value)
{
return Utils::Apply<GetConstexprSize, TupleTransformType<T>>::value;
}
else
{
return ByteVector::Size(ByteConverter<T>::TupleTransform(obj));
}
}
#else
/// @brief Default implementation of Size method with compile time evaluation.
/// @return size_t. Number of bytes used after serialization.
template <typename C = TupleTransformType<T>, std::enable_if_t<Utils::Apply<IsSizeConstexpr, C>::value, int> = 0>
static constexpr size_t Size()
{
return Utils::Apply<GetConstexprSize, C>::value;
}
/// @brief Default implementation of Size method.
/// @param obj Object for serialization.
/// @return size_t. Number of bytes used after serialization.
template <typename C = TupleTransformType<T>, std::enable_if_t<!Utils::Apply<IsSizeConstexpr, C>::value, int> = 0>
static size_t Size(T const& obj)
{
return ByteVector::Size(ByteConverter<T>::TupleTransform(obj));
}
#endif
/// @brief Default implementation of To method.
/// Serializes data treating it as tuple generated by TupleTransform.
@ -310,12 +366,13 @@ namespace FSecure
bv.Store(ByteConverter<T>::TupleTransform(obj));
}
/// @brief Default implementation of Size method.
/// @param obj Object for serialization.
/// @return size_t. Number of bytes used after serialization.
static size_t Size(T const& obj)
/// @brief Use it to read from ByteView to tuple of types deduced from TupleTransform.
/// This is a helper method used to create dedicated logic of type reading after all data was retrieved form view as tuple.
/// @param bv. Buffer with serialized data.
/// @return tuple of retrieved data for type construction.
static auto ReadTuple(ByteView& bv)
{
return ByteVector::Size(ByteConverter<T>::TupleTransform(obj));
return bv.Read<TupleTransformType<T>>();
}
/// @brief Default implementation of From method.

View File

@ -320,4 +320,20 @@ namespace FSecure::Utils
}
};
}
/// @brief Constexpr helper to perform logic on tuple types. Evaluation result is assigned to value member.
/// @tparam T Class with function to be applied. Must define template<typename...> constexpr auto Apply(). Tuple types will be passed by parameter pack.
/// @tparam Tpl Tuple with types on which logic will be applied.
template <typename T, typename Tpl>
struct Apply
{
private:
template <size_t ...Is>
constexpr static auto ApplyImpl(std::index_sequence<Is...>)
{
return T::template Apply<std::tuple_element_t<Is, Tpl>...>();
}
public:
constexpr static auto value = ApplyImpl(std::make_index_sequence<std::tuple_size<Tpl>::value>{});
};
}