Форум программистов, компьютерный форум CyberForum.ru

особенности передачи по "&&" - C++

Восстановить пароль Регистрация
 
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 01:21     особенности передачи по "&&" #1
я не знаю как называется передача по "&&" . я называю "по двум загогулинам."
вопрос №1: есть работающий код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
void foo(const int&)
{    std::cout << "Hello! I'm foo(const int&)" << std::endl;  }
 
void foo(int&&)
{  std::cout << "Hello! I'm foo(int&&)" << std::endl; }
 
template <class T>
void bar(T&& t)
{     foo(t);  }
 
int main()
{   bar(42);
    return 0;
}
почему если bar принимает 42 "по двум загогулинам." то внутри него foo использует 42 как const int& и пишет соответственно "Hello! I'm foo(const int&)" (про std::forward я знаю)
вопрос №2:
если не использовать шаблон, то будет облом - почему?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
void foo(const int&)
{    std::cout << "Hello! I'm foo(const int&)" << std::endl;  }
 
void foo(int&&)
{  std::cout << "Hello! I'm foo(int&&)" << std::endl; }
 
void bar(int&& t) // убираем template
{    foo(t); }
int main()
{    int a = 42;
    bar(a); // cannot bind 'int' lvalue to 'int&&'
    return 0;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
16.07.2013, 01:40     особенности передачи по "&&" #2
soican, там есть правила вывода, если T - "выводимый" (deduced) тип. Тип t зависит от типа передаваемого в функцию параметра:
передали lvalue - получили lvalue ссылку (&); передали rvalue - rvalue ссылку (&&).

Добавлено через 2 минуты
Цитата Сообщение от soican Посмотреть сообщение
сли не использовать шаблон, то будет облом - почему?
Потому что a - это lvalue. Нельзя привязать lvalue к rvalue ссылке. Попробуй:
C++
1
bar(42);
или
C++
1
bar(std::move(a));
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 01:45  [ТС]     особенности передачи по "&&" #3
Цитата Сообщение от gray_fox Посмотреть сообщение
Нельзя привязать lvalue к rvalue ссылке.
это понял
Цитата Сообщение от gray_fox Посмотреть сообщение
там есть правила вывода, если T - "выводимый" (deduced) тип.
это не понял, как шаблон всё таки умудряется обойти правило "Нельзя привязать lvalue к rvalue ссылке." и в шаблоне пишут зачемто class
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
16.07.2013, 01:53     особенности передачи по "&&" #4
Цитата Сообщение от soican Посмотреть сообщение
это не понял, как шаблон всё таки умудряется обойти правило "Нельзя привязать lvalue к rvalue ссылке."
Он не обходит, "у него свои". T && превращается в T & либо T && (не учитывая cv) в зависимости от типа переданного аргумента (lvalue/rvalue).

Добавлено через 5 минут
soican, можно погуглить reference collapsing rules
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 04:12  [ТС]     особенности передачи по "&&" #5
Цитата Сообщение от gray_fox Посмотреть сообщение
можно погуглить reference collapsing rules
я погуглил, пока въезжаю...но суть вопроса такая,(вопроса №1):
bar принимает 42(rvalue) по &&. а внутри него foo использует 42 как const int&, а не как int&&

Добавлено через 1 час 29 минут
оформлю свой вопрос в код:
C++
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
#include <iostream>
void foo(const int&)
{    std::cout << "Hello! I'm foo(const int&)" << std::endl;  }
void foo(int&&)
{  std::cout << "Hello! I'm foo(int&&)" << std::endl; }
template <class T>
void bar(T&& t)
{   foo(std::move(t));
    foo(std::forward<T>(t));
    foo(t);
}
int main()
{    int i=45;
    bar(42);  bar(i);
/*результат запуска:
Hello! I'm foo(int&&)    // std::move возвращает &&
 
Hello! I'm foo(int&&)      //forward возвратит && только если не сможет возвратить &
                           // в даннном случае(bar(42)) не смог => int&&
Hello! I'm foo(const int&) // ПОЧЕМУ!!!!!!!
 
Hello! I'm foo(int&&)      // std::move возвращает &&
 
Hello! I'm foo(const int&) //forward возвратит && только если не сможет возвратить &
                           // в даннном случае(bar(i)) смог => const int&
 
Hello! I'm foo(const int&) // изначально на этапе создания ф-ции из шаблона T&& превратилось в T&
                           // т.к. int i обладает адресом и является lvalue
*/
    return 0;
}
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2013, 07:40     особенности передачи по "&&" #6
soican, Потому что t в функции это lvalue, а не rvalue.
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 11:18  [ТС]     особенности передачи по "&&" #7
Цитата Сообщение от ForEveR Посмотреть сообщение
Потому что t в функции это lvalue, а не rvalue.
странно что это и в случае "42" и в случае "int i=42"
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11811 / 6790 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
16.07.2013, 11:25     особенности передачи по "&&" #8
soican, что странного?
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 11:28  [ТС]     особенности передачи по "&&" #9
Цитата Сообщение от Croessmah Посмотреть сообщение
что странного?
bar принимает 42 по && а уже внутри него foo использует 42 как const int& и пишет соответственно "Hello! I'm foo(const int&)". вот я и не могу понять логику
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2013, 11:36     особенности передачи по "&&" #10
soican, Потому что переменная является lvalue. Сама по себе переменная в функции является lvalue.
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 11:41  [ТС]     особенности передачи по "&&" #11
Цитата Сообщение от ForEveR Посмотреть сообщение
Сама по себе переменная в функции является lvalue.
но у нас же есть две функции:
C++
1
2
void foo(const int&){   } 
void foo(int&&){   }
вот в bar мы запихали 42 по && а теперь в foo 42 идёт по const int&
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2013, 11:43     особенности передачи по "&&" #12
soican, t - lvalue. В функции bar(T&& t) - t в контексте функции является lvalue.
Может быть такой пример даст больше понимания
C++
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
36
37
38
39
40
41
#include <iostream>
 
class C
{
public:
   C() {}
   C(const C&)
   {
      std::cout << "copy" << std::endl;
   }
   C(C&&)
   {
      std::cout << "move" << std::endl;
   }
};
 
class Copyable
{
public:
   Copyable(C&& c) : obj(c)
   {
   }
private:
   C obj;
};
 
class Moveable
{
public:
   Moveable(C&& c) : obj(std::move(c))
   {
   }
private:
   C obj;
};
 
int main()
{
   Copyable copy{C()};
   Moveable move{C()};
}
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
16.07.2013, 12:13     особенности передачи по "&&" #13
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <type_traits>
 
template <class T>
void bar(T&& t)
{   
    std::cout << std::boolalpha 
    << "is rvalue: " << std::is_rvalue_reference<decltype(t)>::value << std::endl
    << "is lvalue: " << std::is_lvalue_reference<decltype(t)>::value << std::endl;
}
int main()
{
    int i=45;
    
    bar(42);
    bar(i);
 
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2013, 12:23     особенности передачи по "&&"
Еще ссылки по теме:

При вызове конструктора ошибка: L "Buffer is too small" & & 0 C++
C++ Ошибка : " L Buffer is too small & & 0"
В чём разница между возвратом "string" и "const string&" & C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
16.07.2013, 12:23  [ТС]     особенности передачи по "&&" #14
Цитата Сообщение от ForEveR Посмотреть сообщение
Может быть такой пример даст больше понимания
хороший пример
но если я напишу Moveable(C&& c) : obj(std::forward<C>(c)) вместо Moveable(C&& c) : obj(std::move(c)) будет тоже самое,а смотри, что написано:
Forward: Returns an rvalue reference to arg if arg is not an lvalue reference.
If arg is an lvalue reference, the function returns arg without modifying its type.
как всё это работает я уже понял, но вот не знаю как объяснить эту фразу

Добавлено через 6 минут
Jupiter, показательно)) вообщем юзать move и forward
Yandex
Объявления
16.07.2013, 12:23     особенности передачи по "&&"
Ответ Создать тему
Опции темы

Текущее время: 06:30. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru