When running the following code, which involves changing the value of a int via a method of a class called B, which inherits from a templated class A, the value of the int doesn't change, and I cannot understand why, I have tested both of these with clang trunk and gcc trunk:
#include <iostream>
template<typename T>
struct A
{
A(T& a_num_) : a_num(a_num_) {}
T& a_num;
};
struct B : public A<int>
{
template<typename... Args>
B(Args... args) : A<int>(args...) {}
void do_something()
{
a_num = 1634;
}
};
int main(void)
{
int num = 4;
B b {num};
b.do_something();
std::cout << num;
return 0;
}
I would expect to get 1634 printed, but instead 4 prints.
I have narrowed the error to the constructor of B, because if I change the constructor of B to be:
B(int& x) : A<int>(x) {}
then the correct value appears, but the current constructor should also be receiving an int, because when I type:
B b {num};
Then it should choose Args = [int&], because that's the only way to satisfy A's constructor, which takes a T&, so what is happening here? What is a_num in this case? Just a garbage reference that doesn't reference anything, or possibly a temporary object?
I've also tried to rewrite the do_something function as
A<int>::a_num = 1634
but it still doesn't manage to change it.
I've also noticed that declaring b as:
B b {6};
Also works, although there's no way 6, which is a pr-value, could bind to a l-value reference.
So my question here is why does B's constructor choose Args = [int] instead of Args = [int&] and how can it do this when it then passes that Args to a constructor that takes a T&?