I’m facing the compilation error in the following code. I’m expecting that even temporary
object can be bound to const reference. So I’m wondering that it should be valid code. However, g++ gives me this error while clang will not give such an error. Does anyone let me know the exact reason why this happens?
#include <iostream>
struct TestClass
{
TestClass() : str()
{
strncpy(str, "hello", sizeof(str));
}
char str[6];
char (&getStr())[6]
{
return str;
}
};
template <typename T>
void printFunc(const T& str)
{
std::cout << str << std::endl;
}
int main()
{
TestClass obj;
printFunc(obj.str);
// printFunc(TestClass().str); // <- This line gives compilation error.
printFunc(TestClass().getStr());
return 0;
};
I would assume that your version of GCC trips over the fact that
TestClass().stris an rvalue array (quite an exotic thing in both C and C++ languages). Something in the specifics of reference initialization when the initailizer is an rvalue is implemented incorrectly. Apparently, the bug was fixed in later versions.Meanwhile both
obj.strandTestClass().getStr()are lvalue arrays. They are handled by the straightforward rules of direct reference binding, so the issue does not arise.To address the comment:
If you modify your function template to
the situation will change drastically. Now it is no longer a reference-binding issue. Now the array-to-pointer conversion rules take over.
In your original version the type
Twas deduced aschar [6], while in this new one it is deduced aschar *. Your array type is completely lost when the argument is passed to the function: it’s a pointer that gets passed instead. This completely eliminates the original issue of reference binding and makes the code compile regardless of the lvalue-ness or rvalue-ness of the array.For example, you can try printing
sizeof strinside your function and observe the difference between the two versions. The original will print your array size in bytes (6), while the new one will print pointer size (4for ideone’s platform).