Invocation: build a solution to adapt std::array

...which should ''basically work,'' since `std::array` is ''»tuple-like«'' —
BUT unfortunately it has a quite distinct template signature which does not fit
into the generic scheme of a product type.

Obviously we'd need a partial specialisation, but even re-implementing this
turns out to be damn hard, because there is no way to generate a builder method
with a suitable explicit type signature directly, because such a builder would
need to accept precisely N arguments of same type. This leads to a different
solution approach: we can introduce an ''adapter type'', which will be layered
on top of `std::array` and just expose the proper type signature so that the
existing Implementation can handle the array, relying on the tuple-protocol.


__Note__: this changeset adds a convenient pretty-printer for `std::array`,
based on the same forward-declaration trick employed recently for `lib::Several`.
You need to include 'lib/format-util.hpp' to actually use it.
This commit is contained in:
Fischlurch 2025-02-17 18:36:23 +01:00
parent 8bb332cc5e
commit 0cad2dacc0
5 changed files with 245 additions and 12 deletions

View file

@ -15,12 +15,12 @@
/** @file format-obj.hpp
** Simple functions to represent objects, for debugging and diagnostics.
** The helpers provided here are rather commonplace, but written in a way
** as to incur only modest header inclusion load. It should be OK to use
** these even on widely used interface headers.
** to incur only modest header inclusion load. It should be OK to use them
** even on interface headers in widespread use.
** - util::toString() performs a failsafe to-String conversion, thereby preferring a
** built-in conversion operator, falling back to a lexical conversion (boost)
** or just a unmangled and simplified type string as default.
** - util::typedString() combines this with a always visible type display
** or just an unmangled and simplified type string as default.
** - util::typedString() combines this with an always visible type display
** - lib::meta::demangleCxx() uses the built-in compiler support to translate a mangled
** type-ID (as given by `typeid(TY).name()`) into a readable, fully qualified
** C++ type name. This is only supported for GNU compatible compilers.

View file

@ -35,6 +35,7 @@
#include "lib/symbol.hpp"
#include "lib/util.hpp"
#include <array>
#include <string>
#include <vector>
#include <sstream>
@ -259,5 +260,17 @@ namespace util {
}
/** convenient pretty-printer for std::array instances */
template<typename T, std::size_t N>
struct StringConv<std::array<T,N>>
{
static std::string
invoke (std::array<T,N> const& arr) noexcept
{
return util::toStringBracket (arr);
}
};
} // namespace util
#endif /*LIB_FORMAT_UTIL_H*/

View file

@ -42,6 +42,7 @@
#include <utility>
#include <tuple>
#include <array>
@ -96,5 +97,91 @@ namespace meta{
};
/* ===== adapt array for tuple-like signature ===== */
template<typename...TTT>
struct ArrayAdapt;
namespace {
template<typename...TTT>
struct AllSame
: std::true_type
{ };
template<typename T1, typename T2, typename...TS>
struct AllSame<T1,T2,TS...>
: __and_<is_same<T1,T2>
,AllSame<T2,TS...>
>
{ };
template<typename T, size_t N>
struct Repeat
{
using Rem = typename Repeat<T, N-1>::Seq;
using Seq = typename Prepend<T,Rem>::Seq;
};
template<typename T>
struct Repeat<T,0>
{
using Seq = TySeq<>;
};
template<typename T, size_t N>
struct _Adapt
{
using NFold = typename Repeat<T,N>::Seq;
using Array = typename RebindVariadic<ArrayAdapt, NFold>::Type;
};
template<typename T, size_t N>
using _AdaptArray_t = typename _Adapt<T,N>::Array;
}
template<typename T, typename...TT>
struct ArrayAdapt<T,TT...>
: std::array<T, 1+sizeof...(TT)>
{
static_assert (AllSame<T,TT...>()
,"Array can only hold elements of uniform type");
using Array = std::array<T, 1+sizeof...(TT)>;
ArrayAdapt (Array const& o) : Array{o} { }
ArrayAdapt (Array && r) : Array{move(r)} { }
template<typename...XS>
ArrayAdapt (XS&& ...inits)
: Array{std::forward<XS> (inits)...}
{ }
};
template<typename T, size_t N>
struct TupleClosureBuilder<std::array<T,N>>
: TupleClosureBuilder<_AdaptArray_t<T,N>>