lumiera_/research/try.cpp
Ichthyostega e6403cbc7e Invocation: get structural bindings to work
It seemed like we're doomed...
Yet we barely escaped our horrid fate, because the C++ structured bindings happen to look also for get<i> member functions!

Any other solution involving a free function `get<i>(h)` would not work, since the `std::tuple` used as base class would inevitably drag in std::get via ADL
Obviously, the other remedy would be to turn the `StorageFrame` into a member; yet doing so is not desirable, as makes the actual storage layout more obscure (and also more brittle)
2024-12-12 19:03:43 +01:00

119 lines
3.2 KiB
C++

/* try.cpp - to try out and experiment with new features....
* scons will create the binary bin/try
*/
// 12/24 - investigate overload resolution on a templated function similar to std::get
// 11/24 - how to define a bare object location comparison predicate
// 11/23 - prototype for grouping from iterator
/** @file try.cpp
* Find out about the conditions when an overload of a function template is picked.
* This is an investigation regarding the proper way to overload `std::get`
* especially when the base class of the custom type itself is a tuple.
*
* As it turns out, overload resolution works as expected; rather the implementation
* of `std::get` causes the problems, as it triggers an assertion immediately when
* instantiated with out-of-bounds parameters, which prevents the overload resolution
* to commence and directly terminates the compilation. The reason is that this
* standard implementation relies on std::tuple_element<I,T> to do the actual
* bounds checking. This can be demonstrated by extracting the standard
* implementation and our custom implementation under a different name.
*/
typedef unsigned int uint;
#include "lib/format-cout.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"
#include "lib/hetero-data.hpp"
#include "lib/util.hpp"
#include <utility>
#include <string>
#include <tuple>
using lib::test::showTypes;
using std::tuple;
struct B { };
struct D1 : B { };
struct D2 : D1 { };
string getty (B&) { return "getty-B&"; }
string getty (D1&&){ return "getty-D1&&"; }
string getty (D1&) { return "getty-D1&"; }
template<class...TS>
string getty (tuple<TS...>&) { return "getty-tuple& "+showTypes<TS...>(); }
template<class...TS>
struct F : tuple<TS...> { };
template<class...TS>
struct FD1 : F<TS...> {};
template<class...TS>
struct FD2 : FD1<TS...> {};
template<class...TS>
string getty (FD1<TS...>&) { return "getty-FD1& "+showTypes<TS...>(); }
template<class...TS>
string getty (lib::HeteroData<TS...>&) { return "getty-Hetero& "+showTypes<TS...>(); }
template<std::size_t __i, typename... _Elements>
// constexpr std::__tuple_element_t<__i, tuple<_Elements...>>&
decltype(auto)
gritty(tuple<_Elements...>& __t) noexcept
{ return std::__get_helper<__i>(__t); }
template<size_t I, typename...DATA>
constexpr std::tuple_element_t<I, lib::HeteroData<DATA...>>&
gritty (lib::HeteroData<DATA...> & heDa) noexcept
{
return heDa.template get<I>();
}
int
main (int, char**)
{
D2 d2;
SHOW_EXPR(getty(d2));
FD2<int, char**> fd2;
SHOW_EXPR(getty(fd2));
using Het = lib::HeteroData<uint,double>;
Het h1;
SHOW_EXPR(getty(h1));
// SHOW_EXPR(std::get<1>(h1) = 5.5)
SHOW_EXPR(h1.get<1>() = 5.5)
using Constructor = Het::Chain<bool,string>;
auto h2 = Constructor::build (true, "Ψ");
h2.linkInto(h1);
using Het2 = Constructor::ChainType;
Het2& chain2 = Constructor::recast (h1);
SHOW_TYPE(Het2)
SHOW_EXPR(getty(chain2));
// SHOW_EXPR(std::get<1>(chain2))
// SHOW_EXPR(std::get<3>(chain2))
SHOW_EXPR(chain2.get<1>())
SHOW_EXPR(chain2.get<3>())
SHOW_EXPR(gritty<1>(chain2))
SHOW_EXPR(gritty<3>(chain2))
cout << "\n.gulp.\n";
return 0;
}