How to use add_lvalue_reference as a template function parameter?

I have seen functions where add_lvalue_reference is used as a template function parameter. Eg:

1
2
3
4
template<typename T>
void f(typename add_lvalue_reference<T>::type t)
{
}


2 questions:

1) How can such a template function be invoked? I have tried something like the following, but its wrong:

1
2
3
int i {};
int& ri {i};
f(ri);


2) Why would anyone want to use such a construct as a function template parameter? What does it mean in this context? Why not just use the following:

1
2
3
4
template<typename T>
void f(T& t)
{
}


Thanks.
That code looks like some Template Meta Programming (TMP). It is used extensively in the STL, and in boost.

There will be a struct add_lvalue_reference<T> somewhere , that has a member type. These structs are used to build other types.

The type traits header <type_traits> is worthwhile looking at, one can see how these are built up. Edit: That's where add_lvalue_reference<T> is defined.

Otherwise google Template Meta Programming :+)

http://en.cppreference.com/w/cpp/types/add_reference
Last edited on
the below function swaps numbers passed by value by adding in the lvalue_reference along the way to variables initialized with the numbers passed by value:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <type_traits>

template <typename T>
void swap(T a, T b)
{
     using Tref = typename std::add_lvalue_reference<T>::type;

    Tref aRef = a;
    Tref bRef  = b;
    T temp = aRef;
    aRef = bRef;
    bRef = temp;
    std::cout << "The numbers swapped are " << aRef << " " << bRef << "\n";
}

int main()
{
    int a {5};
    int b {6};
    swap (a, b);
}

edit: why use it? because sometimes we may not have control over source of a function's argument which could be the return value of yet another function and so we might need to add in the lvalue_reference explicitly
similary rvalue_reference (both add and remove) in the case of move semantics
Last edited on
SSteven wrote:
How can such a template function be invoked?


1
2
    int n;
    f<int>(n);

demo: http://coliru.stacked-crooked.com/a/95bf64ea1d9231e2
> template< typename T > void f( typename std::add_lvalue_reference<T>::type r ) ;
> How can such a template function be invoked?

Because in the parameter, T appears to the left of ::, it appears in a non-deduced context.
The type has to be explicitly specified. For example: int i = 7 ; f<int>(i) ;


> Why would anyone want to use such a construct as a function template parameter?

Such a construct (force a template parameter to be in a non-deduced context) is useful when we do not want a particular argument to participate in template argument deduction, but we want it to use the type that was deduced for some other argument. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <type_traits>
#include <string>

template< typename T > void foo( T&, typename std::remove_reference<T>::type ) {}

template< typename T > void bar( T&, T ) {}

int main ()
{
    std::string a = "abcd" ;
    foo( a, "efgh" ) ; // fine: T is deduced as std::string
    bar( a, "efgh" ) ; // ***error: deduction failed (ambiguous)

    double d = 7 ;
    foo( d, 22 ) ; // fine: T is deduced as int double
    bar( d, 22 ) ; // ***error: deduction failed (ambiguous)
}

http://coliru.stacked-crooked.com/a/cbc1fc6761a06828
Last edited on
Topic archived. No new replies allowed.