In the following code, what is the advantage of using &&
?
The code is from answer at Specialize same operator for different traits
From this question, I get that an &&
argument means it is a reference that can be modified by the function.
The decay_t
probably prevents the compiler to interpret a reference to a variable as an array, as in What is std::decay and when it should be used?
std::forward
is perfect forwarding as described here. Why do we need this forwarding?
Thanks.
#include <iostream>
#include <type_traits>
#include<utility>
class A;
template <typename T>
struct is_A : std::false_type {};
template <> struct is_A<A> : std::true_type {};
template <typename T>
struct is_int : std::false_type {};
template <> struct is_int<int> : std::true_type {};
template <> struct is_int<long> : std::true_type {};
class A{
public:
int val;
void print(void){
std::cout << val << std::endl;
}
template <typename T1>
std::enable_if_t<is_int<std::decay_t<T1>>::value, void>
operator=(T1 && input){
val = 2*std::forward<T1>(input);
}
template <typename T1>
std::enable_if_t<is_A<std::decay_t<T1>>::value,void>
operator=(T1 && Bb){
val = 5*std::forward<T1>(Bb).val;
}
};
int main(void){
A Aa;
A Bb;
int in_a = 3;
Aa = in_a;
Bb = Aa;
Aa.print(); //This should give 6. (3x2)
Bb.print(); //This should give 30. (6x5)
}
Actually, it's a (let me say) trick so as the example code works.
In fact, the standard says that:
A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatileX&.
Moreover:
If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly.
Now, try to copy-assign a const reference to the variable, as an example:
Bb = static_cast<const A&>(Aa);
The result will be no longer the one expected.
Anyway, as long as you deal only with non cv-qualified lvalue/rvalue references, the forwarding reference used in the answer works fine, as shown in the example code.
It intercepts a bunch of specific types and does its work. That's all.
As mentioned in the comments by @Jarod42:
Note that you still have to write the
operator=(const A&)
to handle it as it is special.
Not so special indeed. You don't have a proper copy assignment operator in that code if you don't define it.
As said in the comments, to define it
[...] is left as an exercise to the reader. :-)
So, what's the advantage of doing that?
A shortcut to offer a minimal, working solution. Not a complete, production-ready piece of code, of course.