Why do I not get guaranteed copy elision with std::tuple?

When constructing std::tuple<int, INeedElision> from {i, {47}}, the selected constructor of std::tuple takes elements by lvalue-reference to const.

tuple( const Types&... args );

Then when use {i, {47}} as the initializer, a temporary INeedElision will be constructed and then passed to the constructor of std::tuple (and get copied). The temporary object will be destroyed immediately and you'll see "Bye" between "A" and "B".

BTW: The 3rd constructor of std::tuple won't be used for this case.

template< class... UTypes >
tuple( UTypes&&... args );

It's a constructor template, and braced-init-list like {47} doesn't have type and can't be deduced by template argument deduction.

On the other hand, if INeedElision has a converting constructor taking int, and make the initializer as {i, 47}, the 3rd constructor of std::tuple will be used and no temporary INeedElision is constructed; the element will be constructed in-place from the int 47.

LIVE