Question

Can you please explain me the difference between mechanism of the following:

int function();

template<class T>
void function2(T&);

void main() {
    function2(function()); // compiler error, instantiated as int &

    const int& v = function();
    function2(v); // okay, instantiated as const int&
}

is my reasoning correct with respect to instantiation? why is not first instantiated as const T&?

Thank you

Was it helpful?

Solution

Because function returns a non-const value. Only objects can be const, because they store some state that could be modified if it weren't const. What you return there is not an object, but a pure value. Conceptually, they are not modifiable (like enumeration constants, for example), but they are not const qualified (like, again, enumeration constants).

OTHER TIPS

I think that you might be confused between rvalues and the const qualifier. function returns a non-const rvalue temporary of type int, so the compiler deduces T to be int, as it should. As you point out, you can bind a temporary to a const ref (c++03 12.2/5), but the compiler will not add cv qualifiers to make a function call well formed. Since you can't control the template function, there are two ways around this (in addition to the solution you posted).

(1) Explicit template parameters: function2<const int>(function())

(2) cv qualify return: const int function();

Both of these solutions are well formed. (1) seems the better solution, IMHO, since (2) is unconventional and silly.

Edit: Actually, the deduced type can be more cv-qualified than the argument for a ref template argument, but only if type deduction would otherwise fail (c++03 14.8.2.1/3). In this case, type deduction doesn't fail, but results in a malformed function call (SFINAE does not apply, because the template function specialization itself is not malformed).

If the intent of the template author was to not modify the argument, it should be declared as a const reference argument, so this may be a bug in the template library, or it may modify the argument, in which case what you are doing will fail where the function attempts to modify the argument.

Edit: As FredOverflow points out, non-class rvalues are always cv unqualified by the standard 3.10/9. So (2), which works under gcc 4.3, is actually a compiler bug (gcc <4.5, according to FredOverflow).

In this line

function2(function()); 

after function2 returns, the argument that passes to it might have its value change, but since function() returns and it's just assigned to a temporary variable, but what would happen to this temporary variable after it goes out of scope is the problem, that's why the compiler complaints.

To compile the first call, it is necessary to define function2 with T&& parameter - this is rvalue, reference to temporary object. In the second call, v is lvalue reference, it is OK. If your compiler doesn't support rvalue references, the first call may be compiled only with T parameter, without reference.

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