Size: a a a

2020 March 16

AB

Artöm Bakri Al-Sarmini in pro.cxx
cpr:
> All destructors found in the C++ standard library are non-throwing
И что, optional в такой ситуации умывает руки?
источник

C

Calculon in pro.cxx
Deleted Account
История из C++ девелопмента
1. App build with armv7a-linux-androideabi23-clang for Android  is *100 times faster* than build for Linux for the same hardware with arm-linux-gnueabihf-g++  (gcc-7.0).
2. This platform is 32bit, so sizeof(std::size_t) = 4.
3. App uses cache which stores data in std::unordered_map<TKey>, with sizeof(TKey) = 8.
4. std::unordered_map uses std::hash to calculate the hash of a key.
5. Implementation std::hash for unsigned long long (which is the same as TKey) in armv7a-linux-androideabi23-clang is the following:

template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)>
struct __scalar_hash;

template <class _Tp>
struct __scalar_hash<_Tp, 2>
   : public unary_function<_Tp, size_t>
{
   size_t operator()(_Tp __v) const _NOEXCEPT
   { /*...*./
       return __murmur2_or_cityhash<size_t>()(&__u, sizeof(__u));
   }
};
struct hash<unsigned long long>
   : public __scalar_hash<unsigned long long>
{
};
6. Implementation std::hash for unsigned long long (which is the same as TKey) in arm-linux-gnueabihf-g++ is the following:

#define _Cxx_hashtable_define_trivial_hash(_Tp)   \
 template<>            \
   struct hash<_Tp> : public __hash_base<size_t, _Tp>  \
   {                                                   \
     size_t                                            \
     operator()(_Tp __val) const noexcept              \
     { return static_cast<size_t>(__val); }            \
   };

 _Cxx_hashtable_define_trivial_hash(unsigned long long)
which is equivalent to return static_cast<std::size_t>(key).
7. data keys have defined structure. Lower bits for nearby keys will be the same. Hence casting key to 32bit integer will produce more or less the same value for different nearby keys.
8. On armv7a linux almost all keys are stored in a single bucket of a hash table.
For such a hash table it will be equivalent of searching in a linked list with a few thousand elements. This explains such a difference in performance.
__murmur
источник

m

magras in pro.cxx
Artöm Bakri Al-Sarmini
is_nothrow_destructible должен корректно работать и в таких классах
Возможно он корректно работает. На cppref для деструктора std::optional::~optional() не проставлен noexcept, то есть используется дефолт, который ничего не кидает.
источник

AT

Andrew Titov in pro.cxx
То есть, нужно что-то вроде

~optional() noexcept(noexcept(declval<T>().~T())) {
...
}
источник

AB

Artöm Bakri Al-Sarmini in pro.cxx
magras
Возможно он корректно работает. На cppref для деструктора std::optional::~optional() не проставлен noexcept, то есть используется дефолт, который ничего не кидает.
И это ожидаемое поведение?
источник

m

magras in pro.cxx
magras
Возможно он корректно работает. На cppref для деструктора std::optional::~optional() не проставлен noexcept, то есть используется дефолт, который ничего не кидает.
В стандарте тоже самое: https://eel.is/c++draft/optional.dtor
То есть это не баг.
источник

m

magras in pro.cxx
Artöm Bakri Al-Sarmini
И это ожидаемое поведение?
А на этот вопрос у меня нет ответа.

Очевидно более сложные контенеры не могут безопасно работать с объектами кидающими исключения из деструтора. optional, наверное, мог бы такое поддержать. Но вроде объекты кидающие из деструтора обычно реализуют scope guard'ы, поэтому их как раз не принято куда-то упаковывать.
источник

v

vehlwn in pro.cxx
Во-первых, ты нарушил главный принцип РАИИ. Во-вторых, у тебя уб. Не хочу искать в стандарте, но вот Майерс:
For some functions, being noexcept is so important, they’re that way by default. In C++98, it was considered bad style to permit the memory deallocation functions and destructors to emit exceptions, and in C++11, this style rule has been all but upgraded to a language rule. By default, all memory deallocation functions and all destructors—both user-defined and compiler-generated are implicitly noexcept.  The only time a destructor is not implicitly noexcept is when a data member of the class (including inherited members and those contained inside other data members) is of a type that expressly states that its destructor may emit exceptions. Such destructors are uncommon. There are none in the Standard Library, and if the destructor for an object being used by the Standard Library (e.g., because it’s in a container or was passed to an algorithm) emits an exception, the behavior of the program is undefined.
источник

m

magras in pro.cxx
vehlwn
Во-первых, ты нарушил главный принцип РАИИ. Во-вторых, у тебя уб. Не хочу искать в стандарте, но вот Майерс:
For some functions, being noexcept is so important, they’re that way by default. In C++98, it was considered bad style to permit the memory deallocation functions and destructors to emit exceptions, and in C++11, this style rule has been all but upgraded to a language rule. By default, all memory deallocation functions and all destructors—both user-defined and compiler-generated are implicitly noexcept.  The only time a destructor is not implicitly noexcept is when a data member of the class (including inherited members and those contained inside other data members) is of a type that expressly states that its destructor may emit exceptions. Such destructors are uncommon. There are none in the Standard Library, and if the destructor for an object being used by the Standard Library (e.g., because it’s in a container or was passed to an algorithm) emits an exception, the behavior of the program is undefined.
А почему UB? Просто terminate, если я ничего не путаю.
источник

m

magras in pro.cxx
vehlwn
Во-первых, ты нарушил главный принцип РАИИ. Во-вторых, у тебя уб. Не хочу искать в стандарте, но вот Майерс:
For some functions, being noexcept is so important, they’re that way by default. In C++98, it was considered bad style to permit the memory deallocation functions and destructors to emit exceptions, and in C++11, this style rule has been all but upgraded to a language rule. By default, all memory deallocation functions and all destructors—both user-defined and compiler-generated are implicitly noexcept.  The only time a destructor is not implicitly noexcept is when a data member of the class (including inherited members and those contained inside other data members) is of a type that expressly states that its destructor may emit exceptions. Such destructors are uncommon. There are none in the Standard Library, and if the destructor for an object being used by the Standard Library (e.g., because it’s in a container or was passed to an algorithm) emits an exception, the behavior of the program is undefined.
Получается, что я не прав? std::optional должен был получить такой же noexcept в деструкторе, как тип лежажий в нем?
источник

AB

Artöm Bakri Al-Sarmini in pro.cxx
vehlwn
Во-первых, ты нарушил главный принцип РАИИ. Во-вторых, у тебя уб. Не хочу искать в стандарте, но вот Майерс:
For some functions, being noexcept is so important, they’re that way by default. In C++98, it was considered bad style to permit the memory deallocation functions and destructors to emit exceptions, and in C++11, this style rule has been all but upgraded to a language rule. By default, all memory deallocation functions and all destructors—both user-defined and compiler-generated are implicitly noexcept.  The only time a destructor is not implicitly noexcept is when a data member of the class (including inherited members and those contained inside other data members) is of a type that expressly states that its destructor may emit exceptions. Such destructors are uncommon. There are none in the Standard Library, and if the destructor for an object being used by the Standard Library (e.g., because it’s in a container or was passed to an algorithm) emits an exception, the behavior of the program is undefined.
По поводу последней фразы найти бы цитату из стандарта, и вопрос отвечен
источник

v

vehlwn in pro.cxx
Artöm Bakri Al-Sarmini
По поводу последней фразы найти бы цитату из стандарта, и вопрос отвечен
Попробуй. У меня не получилось https://t.me/ProCxx/309081
источник
2020 March 17

A

Alex in pro.cxx
Какой-то из динамических контейнеров позволяет объявить себя с неполным типом элемента?
источник

S

Stas in pro.cxx
Alex
Какой-то из динамических контейнеров позволяет объявить себя с неполным типом элемента?
Если речь про forward declaration, то наверно все.
https://godbolt.org/z/nvNMak
источник

A

Alex in pro.cxx
Да, я это имел в виду. Странно, был в полной уверенности, что так нельзя, сейчас даже нагуглил много статей о том, почему нельзя, и ни одной о том , как можно. Но они все старые, времён С++03.
источник

SS

Sergey Sobolev in pro.cxx
Скорее всего с array только не прокатит
источник

A

Alex in pro.cxx
Это в С++11 стало можно?
источник

S

Stas in pro.cxx
Alex
Это в С++11 стало можно?
Александр Фокин говорил, что на 11-ых писал это.
https://youtu.be/I0oerm0MYQY?t=4634
источник

A

Alex in pro.cxx
Спасибо! За лекцию, и за подтверждение, что так можно. Очень выручили, я уже собирался какого-то монстра костылить через PIMPL.
источник

IZ

Ilia Zviagin in pro.cxx
Alex
Какой-то из динамических контейнеров позволяет объявить себя с неполным типом элемента?
Никакой.
источник