How come variables passed by reference do not get assigned to?

Question!

Please consider the 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 its commented output (debug output removed for clarity but available at IDEone):

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

I must be missing something obvious here: from the above, calling Foo<...>::bar(...) only modifies the first set of two non-const parameters. Why are the values of the next arguments left untouched within main?

By : dummydev


Answers

You need to use references on the varargs part of the template or the arguments beyond the first four will be passed to the initial call by value (copying to local variables). The subsequent calls will mutate those copied values, not the original arguments passed.

Since you want to accept rvalues for some of the arguments, use perfect forwarding for varargs to preserve the original types. Just change:

static void bar(T


This video can help you solving your question :)
By: admin