Library: continue Investigation with workaround, inconclusive yet
A simple yet weird workaround (and basically equivalent to our helper function) is to wrap the argument tuple itself into std::forward<Args> -- which has the effect of exposing RValue references to the forwarding function, thus silencing the compiler. I am not happy with this result, since it contradicts the notion of perfect forwarding. As an asside, the ressearch has sorted out some secondary suspicions.. - it is *not* the Varargs argument pack as such - it is *not* the VerbToken type as such The problem clearly is related to exposing tuple elements to a forwarding function.
This commit is contained in:
parent
805d83c2db
commit
5191073558
3 changed files with 46 additions and 34 deletions
|
|
@ -46,7 +46,14 @@
|
|||
|
||||
/** @file try.cpp
|
||||
* Research how to apply a tuple to a varargs function forwarder.
|
||||
* The recent stadard library has a std::apply, which we can not yet use, unfortunately.
|
||||
* The recent standard library has a std::apply, which we can not yet use, unfortunately.
|
||||
* @note this research remains inconclusive. As far as I can see, the simplified setup
|
||||
* exactly mimics the problematic call situation; however, in the real use case,
|
||||
* we need to std::forward<Args> the argument tuple object field while here in
|
||||
* this simplified case, it compiles just fine without -- as it should after all,
|
||||
* since that is the whole point of perfect forwarding; std::get should expose
|
||||
* a LValue reference to the tuple element, and we pass that through a forwarding
|
||||
* function into the double dispatch to the receiving visitor.
|
||||
*/
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
|
@ -73,7 +80,7 @@ using std::tuple;
|
|||
|
||||
template<typename FUN, typename...ARGS>
|
||||
void
|
||||
forwardInvoker (FUN fun, ARGS&&... args)
|
||||
forwardInvoker (FUN& fun, ARGS&&... args)
|
||||
{
|
||||
cout << "forwardInvoker...\n"
|
||||
<< lib::test::showVariadicTypes(args...)
|
||||
|
|
@ -81,28 +88,39 @@ forwardInvoker (FUN fun, ARGS&&... args)
|
|||
fun (std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
template<typename FUN, class TUP, size_t...idx>
|
||||
template<typename FUN, typename...ARGS>
|
||||
struct Holder
|
||||
{
|
||||
using Tup = tuple<ARGS...>;
|
||||
|
||||
Tup tup;
|
||||
|
||||
Holder (Tup& tup)
|
||||
: tup{tup}
|
||||
{ }
|
||||
|
||||
template<size_t...idx>
|
||||
void
|
||||
unpack_and_forward (FUN&& fun, TUP& tup, lib::meta::IndexSeq<idx...>)
|
||||
unpack_and_forward (FUN& fun, lib::meta::IndexSeq<idx...>)
|
||||
{
|
||||
cout << "unpack_and_forward...\n";
|
||||
SHOW_TYPE (TUP)
|
||||
SHOW_TYPE (Tup)
|
||||
|
||||
forwardInvoker (std::forward<FUN>(fun), std::get<idx> (std::forward<TUP>(tup))...);
|
||||
forwardInvoker (fun, std::get<idx> (tup)...);
|
||||
}
|
||||
|
||||
template<typename FUN, typename...ARGS>
|
||||
void
|
||||
applyTuple (FUN&& fun, tuple<ARGS...>& args)
|
||||
applyTuple (FUN& fun)
|
||||
{
|
||||
using Tup = tuple<ARGS...>;
|
||||
cout << "applyTuple...\n";
|
||||
SHOW_TYPE (Tup)
|
||||
|
||||
using SequenceIterator = typename lib::meta::BuildIdxIter<ARGS...>::Ascending;
|
||||
|
||||
unpack_and_forward (std::forward<FUN>(fun), args, SequenceIterator());
|
||||
unpack_and_forward (fun, SequenceIterator());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -110,13 +128,15 @@ applyTuple (FUN&& fun, tuple<ARGS...>& args)
|
|||
int
|
||||
main (int, char**)
|
||||
{
|
||||
auto tup = std::make_tuple(1,2,3u);
|
||||
auto tup = std::make_tuple(1,2,3);
|
||||
auto fun = [](int a, int b, int c)
|
||||
{
|
||||
cout << a<<"+"<<b<<"+"<<c<<"="<<(a+b+c)<<endl;
|
||||
};
|
||||
|
||||
applyTuple (fun, tup);
|
||||
using Hol = Holder<decltype(fun), int, int, int>;
|
||||
Hol holder(tup);
|
||||
holder.applyTuple (fun);
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -70,21 +70,6 @@ namespace lib {
|
|||
{
|
||||
return argStorage + VERB_TOKEN_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper: pass a reference to an tuple element into a "perfect forwarding" call
|
||||
* This is the equivalent of calling std::forward<TY> (TY&)
|
||||
* ////////////////////////////////////////////////////////////////////TODO verify this reasoning is sound!!
|
||||
*/
|
||||
template<size_t idx, typename...ARGS>
|
||||
decltype(auto) constexpr
|
||||
get_ref (std::tuple<ARGS...>& tuple)
|
||||
{
|
||||
using Elm = std::remove_reference_t<
|
||||
std::tuple_element_t<idx, std::tuple<ARGS...>>>;
|
||||
|
||||
return static_cast<Elm&&> (std::get<idx> (tuple));
|
||||
}
|
||||
}
|
||||
|
||||
template<class REC, class RET>
|
||||
|
|
@ -126,8 +111,8 @@ namespace lib {
|
|||
template<size_t...idx>
|
||||
RET
|
||||
invokeVerb (REC& receiver, meta::IndexSeq<idx...>)
|
||||
{
|
||||
return verb_.applyTo (receiver, get_ref<idx> (args_)...);
|
||||
{ //////////////////////////////////////////TICKET #1006 | TICKET #1184 why do we need std::forward here? the target is a "perfect forwarding" function, which should be able to receive a LValue reference to the tuple element just fine...
|
||||
return verb_.applyTo (receiver, std::get<idx> (std::forward<Args>(args_))...);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -150,6 +135,13 @@ namespace lib {
|
|||
VerbPack (Handler<ARGS...> handler, Literal verbID, ARGS&&... args)
|
||||
: PolyHolder(PayloadType<ARGS...>(), handler, verbID, std::forward<ARGS>(args)...)
|
||||
{ }
|
||||
|
||||
RET
|
||||
applyTo (REC& receiver)
|
||||
{
|
||||
VerbInvoker<REC,RET>& dispatch(*this);
|
||||
return dispatch.applyTo (receiver);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -161,11 +161,11 @@ namespace test{
|
|||
render_verbose (TokenSeq& tokens)
|
||||
{
|
||||
VerboseRenderer receiver;
|
||||
// for (Token tok : tokens)
|
||||
// cout << "dispatching " << tok
|
||||
// << " -> '"
|
||||
// << tok.applyTo(receiver)
|
||||
// << "'\n";
|
||||
for (Token tok : tokens)
|
||||
cout << "dispatching " << tok
|
||||
<< " -> '"
|
||||
<< tok.applyTo(receiver)
|
||||
<< "'\n";
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue