7

I have a sample code below.

#include<iostream>

template<typename T>
class XYZ
{
   private:
   T & ref;
   public:
   XYZ(T & arg):ref(arg)
   {
   }
};
class temp
{
   int x;
   public:
   temp():x(34)
   {
   }
};
template<typename T>
void fun(T & arg)
{
}
int main()
{
   XYZ<temp> abc(temp());
   fun(temp());  //This is a compilation error in gcc while the above code is perfectly valid. 
}

In the above code even though XYZ constructor takes argument as non const reference, it compiles fine while the fun function fails to compile. Is this specific to g++ compiler or c++ standard has to say something about it?

Edit:

g++ -v gives this.

gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
chappar
  • 7,275
  • 12
  • 44
  • 57

2 Answers2

12
 XYZ<temp> abc(temp());

It compiles, because it is NOT a variable declaration. I'm sure you think its a variable declaration when the fact is that its a function declaration. The name of the function is abc; the function returns an object of type XYZ<temp> and takes a single (unnamed) argument which in turn is a function returning type temp and taking no argument. See these topics for detail explanation:

And fun(temp()) doesn't compile, because temp() creates a temporary object and a temporary object cannot be bound to non-const reference.

So the fix is this : define your function template as:

template<typename T>
void fun(const T & arg) //note the `const`
{
}
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    Nawaz, you are spot on. When I added another member function called memberFun and tried calling that using abc, I got the following error "temp.cpp:41:8: error: request for member ‘memberFun’ in ‘abc’, which is of non-class type ‘XYZ(temp (*)())." – chappar Jun 07 '11 at 16:25
  • @chappar: Exactly. `abc` is not an object of type `XYZ`. That is why you cannot call any member function of `XYZ` using `abc`. – Nawaz Jun 07 '11 at 16:27
5

No, the standard doesn't allow to pass a temporary to non const reference. (C++0X introduced rvalue reference to allow this in some controlled cases), see 8.5.3/5 (which is too long for me to cite, the meaningful part is otherwise, the reference shall be to a non-volatile const type, but you have to read the whole list of cases to know that they don't apply here).

And

XYZ<temp> abc(temp());

is simply yet another example of the most vexing parse.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143