Что static_cast<T> делает с T&?
Так что я задал этот вопрос, и я возился с его решением через static_cast
, (Между прочим, это решает проблему, я просто не уверен, понимаю ли я почему.)
В коде:
vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);
Это static_cast
просто построить R-значение int
? Какая разница между этим и просто вызовом:
replace(begin(foo), end(foo), int{foo.front()}, 13);
РЕДАКТИРОВАТЬ:
Как следует из ответов static_cast
действительно строит R-значение int
: http://ideone.com/dVPIhD
Но этот код не работает в Visual Studio 2015. Это ошибка компилятора? Проверьте здесь: http://webcompiler.cloudapp.net/
2 ответа
Да, это так же, как
int{...}
если.front()
возвратил тип, который требовал сужающего преобразования. В таком случае,int(...)
будет идентичнымВ случае ошибки программиста статическое приведение с меньшей вероятностью может сделать что-то опасное, например, преобразовать указатель в int, чем
int(...)
,
Обратите внимание, что устранение приведений приводит к неопределенному поведению, так как передний элемент изменяется операцией замены, и это может привести к поломке std::replace
,
я хотел бы использовать
template<class T>
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); }
Я здесь.
Что касается того, почему это не работает в MSVC...
MSVC помогает в ситуациях, когда вы приводите переменную типа T
к T
и продолжает ничего не делать. Это нарушает ваш код.
Существует флаг компилятора (/Zc:rvalueCast), который можно использовать, чтобы MSVC больше не нарушал ваш код.
Функция-член 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);