Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem by a reference variable of a template parameter

The following small example shows my problem:

template<class T> struct X
{
    static void xxx(T& x) { }
    static void xxx(T&& x) { }
};

int main(int argc, char** argv)
{
    int x = 9;
    X<int>::xxx(x); // OK.
    X<int&>::xxx(x); // ERROR!
    return 0;
}

Error message (GCC):

error: ‘static void X::xxx(T&&) [with T = int&]’ cannot be overloaded
error: with ‘static void X::xxx(T&) [with T = int&]’

Why? T = int& ---> Is T& replaced by int&& in static void xxx(T& x)?

If the answer to the question is yes, then:

  • T& is not a lvalue-reference and it becomes a rvalue-reference!
  • And the following code should work:

But it didn't:

template<class T> struct X
{
    static void xxx(T& x) { }
};

int main(int argc, char** argv)
{
    X<int&>::xxx(2); // ERROR!
    return 0;
}

Error Message (GCC):

error: no matching function for call to ‘X::xxx(int)’
note: candidates are: static void X::xxx(T&) [with T = int&]

Then T& with T = int& is not equal to T&& and is not a rvalue-reference. but if it is not, why the first example not working? (it's a recursive problem!)


But the similar problem didn't occur for pointer types:

#include <iostream>

template<class T> struct X
{
    static void xxx(T* x) { std::cout << **x << std::endl; }
};

int main(int argc, char** argv)
{
    int x = 10;
    int* xx = &x;
    X<int*>::xxx(&xx); // OK. call X<int*>::xxx(int**)
    return 0;
}

Why references are different in this behavior?

like image 511
Sadeq Avatar asked Aug 22 '10 17:08

Sadeq


People also ask

What is reference variable with example?

Reference variable is an alternate name of already existing variable. It cannot be changed to refer another variable and should be initialized at the time of declaration and cannot be NULL. The operator '&' is used to declare reference variable. The following is the syntax of reference variable.

What is a template template parameter in C++?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

How do you create a reference variable of an existing variable?

When a variable is declared as a reference, it becomes an alternative name for an existing variable. A variable can be declared as a reference by putting '&' in the declaration.

What is the purpose of reference variable?

A reference variable provides a new name to the existing variable. It is de-referenced implicitly and does not need a de-referencing operator(*) to retrieve the value referenced. Whereas, to retrieve the value pointed to by a pointer we need de-referencing operator(*) which is known as explicit de-referencing.


1 Answers

The C++11 language standard has an explanation of how this works at §8.3.2[dcl.ref]/6 (reformatted for readability):

If a typedef, a type template-parameter, or a decltype-specifier denotes a type TR that is a reference to a type T,

  • an attempt to create the type "lvalue reference to cv TR" creates the type "lvalue reference to T"
  • an attempt to create the type "rvalue reference to cv TR" creates the type TR.

Let's consider your example (I've renamed your T to be TR so it matches the language above):

template<class TR> struct X
{
    static void xxx(TR& x)  { }
    static void xxx(TR&& x) { }
};

If we try instantiating X with TR = int& (so, T = int), the instantiations of xxx are as follows:

static void xxx(TR& x)  { }   -->   static void xxx(int& x) { }
static void xxx(TR&& x) { }   -->   static void xxx(int& x) { }

In the first case, we attempt to create an "lvalue reference to TR," which becomes an "lvalue reference to T." T is int, so the parameter type becomes int&.

In the second case, we attempt to create an "rvalue reference to TR," which becomes TR, which is int&.

The parameter type is the same for both overloads, hence the error.

like image 116
James McNellis Avatar answered Sep 19 '22 15:09

James McNellis