Question

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;
};
Was it helpful?

Solution

I would assume that your version of GCC trips over the fact that TestClass().str is 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.str and TestClass().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

template <typename T> printFunc(const T str)

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 T was deduced as char [6], while in this new one it is deduced as char *. 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 str inside 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 (4 for ideone's platform).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top