Well, apart from poor quality of implementation of std::variant
sometimes. For example, libstdc++'s for GCC 7.1 appears to always use
type erased memory allocation. Which, frankly, is daft in C++ 14 when
you are storing either an int or a std::error_code. I would also assume
that std::bad_alloc can be thrown from libstdc++'s std::variant<> :(
{{citation needed}}.
See what you make of my toy std::variant<> based Outcome at:
https://tinyurl.com/ybxwlewh
libstdc++'s <variant> may have problems, but dynamic allocation (which
would be completely nonconforming) is not one of them.
I think I was wrong about the dynamic memory allocation maybe, but
something very odd is being done with type erasure. libstdc++'s variant
certainly uses a vtable which Dinkumware's does not. Operator=() vectors
via that vtable, and that wrecks code folding by the optimiser such that
the main() function fully expands into all the checks of state every
single operation with potential exception throws, rather than being
pruned into a minimum set of assembler.
Contrast that libstdc++ spew with what Dinkumware STL outputs which is
short enough to paste here:
int main(void) {
00007FF7DEED2200 sub rsp,88h
00007FF7DEED2207 mov qword ptr [rsp+20h],0FFFFFFFFFFFFFFFEh
{
static_checked_result<int> a(5), b(6);
std::cout << a.value() << std::endl;
00007FF7DEED2210 mov edx,5
00007FF7DEED2215 mov rcx,qword ptr [__imp_std::cout
(07FF7DEED4118h)]
00007FF7DEED221C call qword ptr
[__imp_std::basic_ostream::operator<<
(07FF7DEED40D0h)]
00007FF7DEED2222 mov rcx,rax
00007FF7DEED2225 call std::endl
(07FF7DEED1680h)
a = b;
std::cout << a.value() << std::endl;
00007FF7DEED222A mov edx,6
00007FF7DEED222F mov rcx,qword ptr [__imp_std::cout
(07FF7DEED4118h)]
00007FF7DEED2236 call qword ptr
[__imp_std::basic_ostream::operator<<
(07FF7DEED40D0h)]
00007FF7DEED223C mov rcx,rax
00007FF7DEED223F call std::endl
(07FF7DEED1680h)
static_checked_result<int>
c(std::make_error_code(std::errc::timed_out));
00007FF7DEED2244 call
std::_Immortalizestd::_Generic_error_category (07FF7DEED15F0h)
00007FF7DEED2249 nop
// std::cout << c.value() << std::endl; // segfaults, as is correct
}
try {
runtime_checked_result<int> a(5), b(6);
std::cout << a.value() << std::endl;
00007FF7DEED224A mov edx,5
00007FF7DEED224F mov rcx,qword ptr [__imp_std::cout
(07FF7DEED4118h)]
00007FF7DEED2256 call qword ptr
[__imp_std::basic_ostream::operator<<
(07FF7DEED40D0h)]
00007FF7DEED225C mov rcx,rax
00007FF7DEED225F call std::endl
(07FF7DEED1680h)
a = b;
std::cout << a.value() << std::endl;
00007FF7DEED2264 mov edx,6
00007FF7DEED2269 mov rcx,qword ptr [__imp_std::cout
(07FF7DEED4118h)]
00007FF7DEED2270 call qword ptr
[__imp_std::basic_ostream::operator<<
(07FF7DEED40D0h)]
00007FF7DEED2276 mov rcx,rax
00007FF7DEED2279 call std::endl
(07FF7DEED1680h)
runtime_checked_result<int>
c(std::make_error_code(std::errc::timed_out));
00007FF7DEED227E call
std::_Immortalizestd::_Generic_error_category (07FF7DEED15F0h)
00007FF7DEED2283 mov dword ptr [rsp+30h],8Ah
00007FF7DEED228B mov qword ptr [rsp+38h],rax
00007FF7DEED2290 movaps xmm0,xmmword ptr [rsp+30h]
00007FF7DEED2295 movups xmmword ptr [rsp+40h],xmm0
00007FF7DEED229A mov byte ptr [rsp+50h],2
std::cout << c.value() << std::endl; // throws
00007FF7DEED229F movdqa xmmword ptr [rsp+30h],xmm0
00007FF7DEED22A5 lea rdx,[rsp+30h]
00007FF7DEED22AA lea rcx,[rsp+58h]
00007FF7DEED22AF call std::system_error::system_error
(07FF7DEED17C0h)
00007FF7DEED22B4 lea rdx,[_TI4?AVsystem_error@std@@
(07FF7DEED5048h)]
00007FF7DEED22BB lea rcx,[rsp+58h]
00007FF7DEED22C0 call _CxxThrowException (07FF7DEED32C0h)
00007FF7DEED22C5 mov edx,dword ptr [0]
00007FF7DEED22CC mov rcx,qword ptr [__imp_std::cout
(07FF7DEED4118h)]
00007FF7DEED22D3 call qword ptr
[__imp_std::basic_ostream::operator<<
(07FF7DEED40D0h)]
00007FF7DEED22D9 mov rcx,rax
00007FF7DEED22DC call std::endl
(07FF7DEED1680h)
00007FF7DEED22E1 nop
} catch (const std::exception &e) {
std::cerr << "Exception thrown: " << e.what() << std::endl;
}
return 0;
00007FF7DEED22E2 xor eax,eax
} catch (const std::exception &e) {
std::cerr << "Exception thrown: " << e.what() << std::endl;
}
return 0;
00007FF7DEED22E4 add rsp,88h
00007FF7DEED22EB ret
I reckon Dinkumware's variant implementation to be pretty much optimal,
lovely. Nice job Microsoft & Dinkumware!
Niall
--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/