These two changes both result in smaller code for std::variant.
The first one means smaller tables of function pointers, because we don't generate an instantiation for the valueless state. Instead we do a runtime branch, marked [[unlikely]] to make _M_reset() a no-op if it's already valueless. In a microbenchmark I couldn't measure any performance difference due to the extra branch, so the code size reduction seems worthwhile. The second one removes a branch from the index() member by relying on unsigned arithmetic. That also results in smaller code and I can't see any downside. * include/std/variant (_Variant_storage<false, _Types...>::_M_reset): Replace raw visitation with a runtime check for the valueless state and a non-raw visitor. (_Variant_storage<false, _Types...>::_M_reset_impl): Remove. (variant::index()): Remove branch. Tested powerpc64le-linux, any objections?
commit a36ecd71f2e7ce95b479d4c06597f2ee0dfe27b1 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed May 15 22:33:31 2019 +0100 Changes to std::variant to reduce code size * include/std/variant (_Variant_storage<false, _Types...>::_M_reset): Replace raw visitation with a runtime check for the valueless state and a non-raw visitor. (_Variant_storage<false, _Types...>::_M_reset_impl): Remove. (variant::index()): Remove branch. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 8c710c30de5..8844c54913f 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -396,19 +396,16 @@ namespace __variant _M_index(_Np) { } - constexpr void _M_reset_impl() - { - __variant::__raw_visit([](auto&& __this_mem) mutable - { - if constexpr (!is_same_v<remove_reference_t<decltype(__this_mem)>, - __variant_cookie>) - std::_Destroy(std::__addressof(__this_mem)); - }, __variant_cast<_Types...>(*this)); - } - void _M_reset() { - _M_reset_impl(); + if (!_M_valid()) [[unlikely]] + return; + + std::__do_visit<void>([](auto&& __this_mem) mutable + { + std::_Destroy(std::__addressof(__this_mem)); + }, __variant_cast<_Types...>(*this)); + _M_index = variant_npos; } @@ -1485,12 +1482,7 @@ namespace __variant { return !this->_M_valid(); } constexpr size_t index() const noexcept - { - if (this->_M_index == - typename _Base::__index_type(variant_npos)) - return variant_npos; - return this->_M_index; - } + { return size_t(typename _Base::__index_type(this->_M_index + 1)) - 1; } void swap(variant& __rhs)