2016-09-16 9 views
4

В следующем коде, в чем преимущество использования &&? Код от ответа на Specialize same operator for different traitsВ чем преимущество && в этом коде?

this От вопроса, я получаю что && аргумент означает, что это ссылка, которая может быть изменена с помощью функции.

The decay_t, вероятно, предотвращает компилятор интерпретировать ссылку на переменную как массив, так как в What is std::decay and when it should be used?

std::forward идеально подходит пересылка, как описано here. Зачем нам эта экспедиция?

Спасибо.

#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) 
} 
+2

'&&' в этом коде полуформально называют ссылками пересылки. Они связываются как с lvalues, так и с rvalues, а 'T1', переданный в' std :: forward', содержит информацию о том, был ли объект изначально значением lvalue или rvalue. Короче говоря, «преимущество» «&&» заключается в том, что он позволяет совершенную пересылку. – KABoissonneault

+1

Итак, все, что нужно для идеальной пересылки ... Это также позволяет избежать создания временной копии любой части аргумента 'T1 && Bb'? – rxu

+1

@rxu: он не будет создавать копию, если функция (или перегрузка оператора) не была переадресована на прием аргумента по значению (или путем пересылки ссылки, а затем сама использует его по методу «проход по значению»). – ShadowRanger

ответ

2

На самом деле, это (позвольте мне сказать) трюк так, как работает код примера.
На самом деле, стандарт говорит, что:

Пользователь объявленного оператор копирующего присваивания X :: оператора = является нестатическим нешаблонном функции члена класса X ровно с одним параметром типа X , X &, const X &, летучий Х & или const volatileX &.

Кроме того:

Если определение класса не явно объявить оператор присваивания копии, один объявлен неявно.

Теперь попробуйте скопировать-назначить константную ссылку на переменную, в качестве примера:

Bb = static_cast<const A&>(Aa); 

Результат будет уже не один ожидалось.

В любом случае, если вы имеете дело только с ссылками на lvalue/rvalue, отличными от CV, ссылка на пересылку, используемая в ответе, отлично работает, как показано в примере кода.
Это перехватывает кучу конкретных типов и выполняет свою работу. Это все.

Как уже упоминалось в комментариях по @ Jarod42:

Обратите внимание, что вы все еще должны написать operator=(const A&), чтобы справиться с этим, как это особенным.

Не так уж и особо. У вас нет надлежащего оператора присваивания копий в этом коде, если вы его не определяете.
Как сказано в комментариях, чтобы определить его

[...] остается в качестве упражнения для читателя. :-)

Итак, в чем преимущество этого?
Ярлык, предлагающий минимальное рабочее решение. Конечно, не полный, готовый к производству кусок кода.