2016-06-22 11 views
6

Так я спросил this question, и я возился с его решением через static_cast. (Кстати это не решает проблему, я просто не уверен, если я понимаю, почему.)Что делает static_cast <T> делать с T &?

В коде:

vector<int> foo = {0, 42, 0, 42, 0, 42}; 
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13); 

ли static_cast просто построения R-Value int? В чем разница между этим и только призыв:

replace(begin(foo), end(foo), int{foo.front()}, 13); 

EDIT:

Как судить по ответам static_castделает кажется, построить R-Value int: http://ideone.com/dVPIhD

Но это код не Работа над Visual Studio 2015. Является ли это ошибкой компилятора? Проверьте здесь: http://webcompiler.cloudapp.net/

+0

Я не котировка какой-либо стандарт, чтобы поддержать меня, но я думаю, что вы можете использовать '+ foo.front()', чтобы получить копию значения, а не ссылки на символ – KABoissonneault

ответ

6
  1. Да, это так же, как int{...}, если .front() не возвращается тип, который требуется сужающее преобразование. В этом случае int(...) будет идентичным.

  2. В случае ошибки программиста, статическое приведение незначительно менее вероятно, сделает что-то опасное, например, превратит указатель в int, а не int(...).

Примечания устранения результатов броска в непредсказуемом поведении, как передний элемент модифицируется операцией замены, и это может нарушить std::replace.

Я хотел бы использовать

template<class T> 
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); } 

себя здесь.

А почему это не работает в MSVC ...

MSVC услужливо принимает ситуации, когда вы разыгрываете переменную типа T к T и продолжает делать нечего. Это нарушает ваш код.

Существует compiler flag (/Zc:rvalueCast), который вы можете использовать, чтобы MSVC больше не нарушал ваш код.

+0

Является ли 'copy_of'standard, или вы говорите, что я должен просто реализовать это? –

+0

@jona Я предлагал реализовать это, поскольку он имеет множество вариантов использования и исключает ненужное повторение типа. – Yakk

+0

Итак, я уточнил свой вопрос, указав разницу между Visual Studio и gcc. Извините, что переместил стойки ворот. –

5

Функция-член front возвращает ссылку на первый элемент непустого вектора.

С другой стороны стандартный алгоритм replace объявлен как

template <class ForwardIterator, class T> 
    void replace (ForwardIterator first, ForwardIterator last, 
       const T& old_value, const T& new_value) 

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

Использование static_cast создает временный объект и не будет изменен алгоритмом. Таким образом, обработка всех элементов вектора будет правильной.

Что касается меня, то я предложил предложение C++ использовать ключевое слово auto в таких случаях. Например

replace(begin(foo), end(foo), auto(foo.front()), 13); 
+1

Предложение 'auto' очень элегантно. +1 –

+1

Авто предложение не скомпилировано: http://coliru.stacked-crooked.com/a/27328ba4ae68d68d – NathanOliver

+1

@NathanOliver Как сказано в ответе, это всего лишь предложение – KABoissonneault