I noticed that libstdc++'s implementation of std::ignore
takes a const T&
argument, which can't bind to a volatile rvalue. Hence the following code fails to compile:
#include <tuple>
#include <utility>
struct C {};
using VC = C volatile;
int main() {
std::tuple<VC> t;
std::tie(std::ignore) = std::move(t);
}
(http://coliru.stacked-crooked.com/a/7bfc499c1748e59e)
Is this in violation of the standard, or is there a clause that renders this undefined behaviour?
I'm not a language lawyer, so I'm going to be answering this question as directly as possible.
ignore
is found in the synopsis of tuple
in tuple.general
as such:
// [tuple.creation], tuple creation functions:
const unspecified ignore;
As you noticed, the libstdc++ implementation defines ignore
like this:
// A class (and instance) which can be used in 'tie' when an element
// of a tuple is not required
struct _Swallow_assign
{
template<class _Tp>
const _Swallow_assign&
operator=(const _Tp&) const
{ return *this; }
};
Whereas the libc++ version defines it like this:
template <class _Up>
struct __ignore_t
{
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY
const __ignore_t& operator=(_Tp&&) const {return *this;}
};
As such, it compiles in libc++. Now the definition of std::tie
can be found in [tuple.creation] which says:
Returns:
tuple<Types&...>(t...)
. When an argument int
isignore
, assigning any value to the corresponding tuple element has no effect.
This doesn't say anything about ignore
itself, so I'm going to chalk this up to unspecified behavior. You can argue it's undefined behavior by omission, but that might be stretching it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With