Avec la solution template, on pourra passer une lvalue car le template sera remplacé par T &.
Et du coup, le compilateur passera une sorte de T & && (en pratique il passera T &) et il n'y aura pas de véritable déplacement. (Je veux bien de vrais explications là-dessus )
Voici un exemple :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
#include <iostream>
#include <type_traits>
class A
{
public:
void operator()() { std::cout << "A::()()" << std::endl; }
};
template <class func_t>
void call(func_t && f)
{
std::cout << "func_t is a & = " << std::is_reference<func_t>::value << std::endl;
std::cout << "func_t is a && = " << std::is_rvalue_reference<func_t>::value << std::endl;
std::cout << " f is a & = " << std::is_reference<decltype(f)>::value << std::endl;
std::cout << " f is a && = " << std::is_rvalue_reference<decltype(f)>::value << std::endl;
f();
}
int main()
{
A a;
call(a);
std::cout << std::endl;
call(A());
std::cout << std::endl;
return 0;
} |
Et voici la sortie :
1 2 3 4 5 6 7 8 9 10 11 12
| $ g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
func_t is a & = 1
func_t is a && = 0
f is a & = 1
f is a && = 0
A::()()
func_t is a & = 0
func_t is a && = 0
f is a & = 1
f is a && = 1
A::()() |
Si on n'avait pas de template mais directement ce code là :
1 2 3 4 5 6
| void call(A && f)
{
std::cout << "& = " << std::is_reference<decltype(f)>::value << std::endl;
std::cout << "&& = " << std::is_rvalue_reference<decltype(f)>::value << std::endl;
f();
} |
On aurait eu une erreur de compilation car la fonction prend uniquement une rvalue et non une lvalue.
error: cannot bind A lvalue to A&&
Partager