А где сравнение производительности то? Из статьи понял, что если надо написать код, который будет создавать в цикле пустые словари и ничего с ними дальше не делать, то лучше использовать {}.
«В отличие от карточных переводов, ввод номера самой банковской карты не потребуется, что минимизирует вероятность ошибки при наборе как у отправителя, так и у получателя»
Так себе аргумент — в номере карты как раз присутствует контрольная сумма для минимизации вероятности ошибки, в отличие от номера телефона или почты.
Атрибут unused про подавление предупреждений компилятора о неиспользуемой переменной. А атрибут used про отключение оптимизации неиспользуемой статической переменной. Так что они не противоположны, как можно предположить из названия, а, наоборот, дополняют друг друга.
Например:
без атрибутов — предупреждение + переменная удалена при компиляции;
unused — предупрежения нет, но переменная всё равно удалена;
used — предупреждение, переменная остаётся в объектном файле;
used unused — предупреждения нет, переменная есть.
Тип аргумента — T&&, а параметра — T. Неопределенное поведение возникает при инициализации параметров, а не вычислении аргументов, что как раз не столь очевидно, как использование в аргументах выражений с побочными эффектами.
Мотивирующий пример:
#include <iostream>
struct C {
C(int&& i) : x(i) {}
C(int& i) : x(i) {++i;}
int x;
};
int f1(const C& c, int i) { return c.x+i; }
int f2(int i, const C& c) { return c.x+i; }
int main() {
int x = 1, y = 1;
std::cout << f1(1,1) << std::endl;
std::cout << f1(x,x) << std::endl;
std::cout << f2(1,1) << std::endl;
std::cout << f2(y,y) << std::endl;
}
clang++: 2
3
2
2
g++: 2
2
2
3
Очевидно, что сам вызов f(x,x) не подразумевает побочных эффектов при вычислении аргументов. Вот здесь то как раз и нужен статический анализатор, на что и мог указать автор.
std::move делает ровно то, что он делает — преобразование типа значения в xvalue. Как использовать полученное значение — для перемещения, чтения, модификации без перемещения и т.п. — уже не касается самой функции.
Так точно, проблема в инициализации параметров, где уже собственно и происходит вызов перемещающего конструктора. А само вычисление аргументов в данном случае не приводит к модификации указателя. В объяснении из статьи использована неверная терминология.
Для примера:
Аргумент (std::move(context), std::make_unique()) будет вычислен, но неопределенного поведения в context->task_runner() не будет, т.к. перемещеия в данном случае не будет.
По первому примеру не могу согласиться: не имеет значения в каком порядке будет «вычислен» std::move, он никак не модифицирует передаваемый аргумент, т.к. производится лишь преобразование типа ссылки — в стандарте указано (20.2.5):
Не нравится мне этот подход с индексированием базовых типов и побочным эффектом у оператора приведения типа. Можно сделать перечисление базовых типов в виде SFINAE специализации шаблона. Например:
Код
#include <iostream>
#include <tuple>
#include <typeinfo>
#include <utility>
namespace reflect {
namespace detail {
template <size_t>
struct ubiq {
template <class T>
constexpr operator T&() const;
};
template <class T>
struct exact {
constexpr operator T&() const;
};
template <class>
using void_t = void;
template <class T, size_t N = sizeof( T ), class S = std::make_index_sequence<N>, class = void>
struct tuple_size_helper : tuple_size_helper<T, N - 1, std::make_index_sequence<N - 1>> {
};
template <class T, size_t N, size_t... I>
struct tuple_size_helper<T, N, std::index_sequence<I...>, void_t<decltype( T{ubiq<I>{}...} )>> {
using type = std::integral_constant<size_t, N>;
};
} // namespace detail
template <class T>
using tuple_size = typename detail::tuple_size_helper<T>::type;
namespace detail {
template <size_t N, class T, class = std::make_index_sequence<N>, class = std::make_index_sequence<tuple_size<T>::value - N - 1>,
class = void>
struct tuple_element_helper;
template <size_t N, class T, size_t... I, size_t... J>
struct tuple_element_helper<N, T, std::index_sequence<I...>, std::index_sequence<J...>,
void_t<decltype( T{ubiq<I>{}..., exact<int>{}, ubiq<J>{}...} )>> {
using type = int;
};
template <size_t N, class T, size_t... I, size_t... J>
struct tuple_element_helper<N, T, std::index_sequence<I...>, std::index_sequence<J...>,
void_t<decltype( T{ubiq<I>{}..., exact<size_t>{}, ubiq<J>{}...} )>> {
using type = size_t;
};
template <size_t N, class T, size_t... I, size_t... J>
struct tuple_element_helper<N, T, std::index_sequence<I...>, std::index_sequence<J...>,
void_t<decltype( T{ubiq<I>{}..., exact<std::string>{}, ubiq<J>{}...} )>> {
using type = std::string;
};
} // namespace detail
template <size_t N, class T>
struct tuple_element {
using type = typename detail::tuple_element_helper<N, T>::type;
};
template <size_t N, class T>
using tuple_element_t = typename tuple_element<N, T>::type;
namespace detail {
template <class T, class = std::make_index_sequence<tuple_size<T>::value>>
struct as_tuple_helper;
template <class T, size_t... I>
struct as_tuple_helper<T, std::index_sequence<I...>> {
using type = std::tuple<tuple_element_t<I, T>...>;
};
} // namespace detail
template <class T>
using as_tuple_t = typename detail::as_tuple_helper<T>::type;
} // namespace reflect
struct s {
int a;
size_t b;
int x;
std::string q;
};
int main()
{
std::cout << reflect::tuple_size<s>() << std::endl;
std::cout << typeid( reflect::tuple_element_t<0, s> ).name() << std::endl;
std::cout << typeid( reflect::tuple_element_t<1, s> ).name() << std::endl;
std::cout << typeid( reflect::tuple_element_t<2, s> ).name() << std::endl;
std::cout << typeid( reflect::tuple_element_t<3, s> ).name() << std::endl;
std::cout << typeid( reflect::as_tuple_t<s> ).name() << std::endl;
}
В переводах уже не надо давать ссылку на оригинал?
なぜsortコマンドはuniq機能を含んでいるのか?(Unix哲学はどこ行った!?)
I love
The Power GloveApple Watch. It's so bad.Я и говорю
А где сравнение производительности то? Из статьи понял, что если надо написать код, который будет создавать в цикле пустые словари и ничего с ними дальше не делать, то лучше использовать
{}
.Нет, абсолютно весь контент теперь принадлежит "аккредитованной организации" по умолчанию. А у правообладателя есть 30 дней доказать, что контент его.
Подавляющее большинство серверов террористов принимает соединения из интернета на 0.0.0.0
https://english.alaraby.co.uk/news/israeli-minister-says-settler-attacks-organised-terrorism
https://edition.cnn.com/2022/01/26/middleeast/west-bank-israeli-settlers-violence-intl/index.html
и т.д.
Разница правда в том, что их обычно не расстреливают сразу на месте как палестницев.
Нужно будет взять на заметку, как вежливо сказать, что чей-то английский говно — «твой английский как у professional white-collars in the US!»
Так себе аргумент — в номере карты как раз присутствует контрольная сумма для минимизации вероятности ошибки, в отличие от номера телефона или почты.
Например:
без атрибутов — предупреждение + переменная удалена при компиляции;
unused — предупрежения нет, но переменная всё равно удалена;
used — предупреждение, переменная остаётся в объектном файле;
used unused — предупреждения нет, переменная есть.
Мотивирующий пример:
clang++:
2
3
2
2
g++:
2
2
2
3
Очевидно, что сам вызов f(x,x) не подразумевает побочных эффектов при вычислении аргументов. Вот здесь то как раз и нужен статический анализатор, на что и мог указать автор.
Для примера:
Аргумент (std::move(context), std::make_unique()) будет вычислен, но неопределенного поведения в context->task_runner() не будет, т.к. перемещеия в данном случае не будет.