Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
Эксперт С++
4967 / 3074 / 456
Регистрация: 10.11.2010
Сообщений: 11,159
Записей в блоге: 10
1

C++11 - std::forward и static_assert

02.11.2014, 19:30. Просмотров 2165. Ответов 5
Метки нет (Все метки)

Привет.
Эта тема создана в познавательных целях.
А именно, мне не совсем понятна реализация шаблонной функции std::forward. Вот так она выглядит в GCC и Clang:
C++
1
2
3
4
5
6
template <typename T>
constexpr T && forward( typename std::remove_reference<T>::type && t ) noexcept
{
    static_assert( !std::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue." ); // текст из Clang
    return static_cast<T &&>( t );
}
В каких случаях может сработать static_assert?
Разнообразными способами я пытался включить этот "триггер", но увы...
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
template <typename T>
void foo( T && t ) {
    std::cout << t << std::endl;
}
 
template <typename T>
void wrapper( T /*&&*/ arg )
{
    foo( forward<T>( arg ) );
}
 
int main()
{
    int lvalue = 5;
    int & lvalue_ref = lvalue;
 
    wrapper( lvalue );
    wrapper( lvalue_ref );
    wrapper( 1 + 2 /* rvalue */ );
 
    foo( forward<int>( lvalue ) );
    foo( forward<int &>( lvalue_ref ) );
    foo( forward<int &&>( 1 + 2 ) /* rvalue */ );
}
Для чего эта проверка? Если кто знает, приведите пример в котором сработает static_assert.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.11.2014, 19:30
Ответы с готовыми решениями:

Применение std::forward
Хочу сделать внутри метода большой обьект. Затем передать его через return. Для этого хочу...

В каком случае используется вторая перегрузка std::forward?
В каком случае используется втарая перегрузка std::forward? //clang 3.8.0 #include...

Зачем в определении std::forward () нужен объект remove_reference?
Зачем в определении std::forward() нужен объект remove_reference ? И почему не могут быть выведены...

Не воспринимает ни std::cout, ни std::cin. Вобщем ничего из std. Также не понимает iostream
Здравствуйте! Я хотел начать изучать язык C++. Набрал литературы. Установил Microsoft Visual C++...

5
2821 / 1630 / 252
Регистрация: 03.12.2007
Сообщений: 4,222
02.11.2014, 19:54 2
Лучший ответ Сообщение было отмечено castaway как решение

Решение

C++
1
forward<int&>(1);
1
Эксперт С++
4967 / 3074 / 456
Регистрация: 10.11.2010
Сообщений: 11,159
Записей в блоге: 10
02.11.2014, 20:11  [ТС] 3
Somebody, благодарю!
0
С чаем беда...
Эксперт CЭксперт С++
8282 / 4056 / 1114
Регистрация: 18.10.2014
Сообщений: 8,759
02.11.2014, 21:34 4
Цитата Сообщение от castaway Посмотреть сообщение
Вот так она выглядит в GCC и Clang:
Во-первых, определение std::forward, которое вы процитировали - это определение из C++14, принятого лишь в августе. "В познавательных целях" совсем не обязательно вовлекать эти определения.

Во-вторых, в С++14 существует четыре перегруженных версии forward. Ваш код не вызывает этого static_assert просто потому, что компилируются и используются другие версии forward, именно те в которых никакого static_assert нет.

Для вашего эксперимента достаточно оргинального forward из C++11, имеющего две перегруженных версии

template <class T> T&& forward(typename remove_reference<T>::type& t) noexcept;
template <class T> T&& forward(typename remove_reference<T>::type&& t) noexcept;

Опять же такой static_assert будет присутствовать только во второй версии. Ваш же оригинальный код, как вы не вертитесь с явной специализацией, будет вызывать именно первую. Чтобы вызвать вторую нужно либо явное rvalue в качестве аргумента, либо применение std::move. Т.е. в контексте вашего кода падать по этому static_assert будет

C++
1
2
3
4
5
6
int bar() { return 5; }
 
...
forward<int &>( 0 );
forward<int &>( bar() );
forward<int &>( move(lvalue) );
1
Эксперт С++
4967 / 3074 / 456
Регистрация: 10.11.2010
Сообщений: 11,159
Записей в блоге: 10
02.11.2014, 22:11  [ТС] 5
Во-первых, определение std::forward, которое вы процитировали - это определение из C++14[/quote]std::forward есть в стандарте C++11.
TheCalligrapher, дело не в том, что я процитировал. Это всего лишь не правильный пример.
Я задал конкретный вопрос, ответ на который уже получен.
Спасибо за ответ.
0
С чаем беда...
Эксперт CЭксперт С++
8282 / 4056 / 1114
Регистрация: 18.10.2014
Сообщений: 8,759
02.11.2014, 22:43 6
Цитата Сообщение от castaway Посмотреть сообщение
Я задал конкретный вопрос, ответ на который уже получен
Считайте, что мой ответ предназначен не для вас, а для случайно прочитавшего данный вопрос неподготовленного зрителя, который недоуменно посмотрит на ваш вопрос и затем на ответ "который уже получен" и немедленно задастся следующим вопросом: с чего бы это вдруг в 'forward<int&>(1)' static_assert стреляет, а в 'forward<int &>( lvalue_ref )' - не стрелял. Тип 'T' ведь и там, и там один и тот же.

P.S. В мой предыдущий ответ закралась неточность: в С++14 две версии forward, а не четыре.
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.11.2014, 22:43

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Выброс static_assert в failure SFINAE
Добрый день, Пролог: куда я только static_assert не пихал))) Проблема: Ошибка error C2794:...

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri
на вод поступают 2 строки типа string. определить количество вхождений строки 2 в строку 1 ошибка...

Static_assert для сравнения адресов объектов
Привет. Бывают такие случаи, когда вроде и понимаешь, но всё-равно что-то не получается... Почему...

Ошибка в static_assert: выражение не определяется константой
template&lt;class T&gt; int fff(T v) { static_assert(typeid(T) == typeid(double), &quot;not accepted...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.