c++ - How come pack expanded variables do not get passed by reference? -


please consider following program:

#include <iostream>   template <typename t, typename ...ts> struct foo {     template <typename ...us>     static void bar(t& ot0, t& ot1, const t& it0, const t& it1, us... args) {         std::cout << " -> foo<...>::bar() enter [ " << ot0 << ", " << ot1 << " ]" << std::endl;         foo<t>::bar(ot0, ot1, it0, it1);         foo<ts...>::bar(args...);         std::cout << " <- foo<...>::bar() exit [ " << ot0 << ", " << ot1 << " ]" << std::endl;     } };  template <typename t> struct foo<t> {     static void bar(t& ot0, t& ot1, const t& it0, const t& it1) {         std::cout << " -> foo<>::bar() enter [ " << ot0 << ", " << ot1 << " ]" << std::endl;         ot0 = it0;         ot1 = it1;         std::cout << " <- foo<>::bar() exit [ " << ot0 << ", " << ot1 << " ]" << std::endl;     } };   int main() {     int i0 = -1,         i1 = 0;     float f0 = -97.18f,           f1 = 3.141592f;     std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;      foo<int, float, int>::bar(i0, i1, 0, 1, f0, f1, 18.f, -7.f, i0, i1, 4, 17);     std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;      foo<float>::bar(f0, f1, 18.f, -7.f);     std::cout << "( " << f0 << ", " << f1 << " ) " << std::endl;      foo<float, int>::bar(f0, f1, 2.71f, 9000.1f, i0, i1, 4, 17);     std::cout << "( "<< i0 << ", " << i1 << "; " << f0 << ", " << f1 << " ) " << std::endl;      return 0; } 

and commented output (debug output removed clarity available @ ideone):

( -1, 0; -97.18, 3.14159 ) // initial values ( 0, 1; -97.18, 3.14159 ) // ints set once?! floats unchanged?! ( 18, -7 )  ( 0, 1; 2.71, 9000.1 ) // ints unchanged?! 

i must missing obvious here: above, calling foo<...>::bar(...) only modifies first set of 2 non-const parameters. why values of next arguments left untouched within main?

you need use references on varargs part of template or arguments beyond first 4 passed initial call value (copying local variables). subsequent calls mutate copied values, not original arguments passed.

since want accept rvalues of arguments, use perfect forwarding varargs preserve original types. change:

static void bar(t& ot0, t& ot1, const t& it0, const t& it1, us... args) { 

to:

// receive varargs forwarding references allow perfect forwarding instead // of receiving them copies static void bar(t& ot0, t& ot1, const t& it0, const t& it1, us&&... args) { 

and change:

foo<ts...>::bar(args...); 

to:

// per earlier link, must explicitly template std::forward call in varargs case foo<ts...>::bar(std::forward<us>(args)...);  

which should receive , forward varargs correctly, received in nested calls whatever type (const or non-const reference) innermost "real" call requires.


Comments

Popular posts from this blog

javascript - Thinglink image not visible until browser resize -

firebird - Error "invalid transaction handle (expecting explicit transaction start)" executing script from Delphi -

mongodb - How to keep track of users making Stripe Payments -