Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the advantage of && in this code?

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)
}
like image 678
rxu Avatar asked Oct 19 '22 01:10

rxu


1 Answers

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.

like image 96
skypjack Avatar answered Nov 15 '22 06:11

skypjack