Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is libstdc++ wrong to reject assignment of volatile rvalue to std::ignore?

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?

like image 848
Brian Bi Avatar asked Jun 20 '16 22:06

Brian Bi


1 Answers

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 in t is ignore, 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.

like image 101
uh oh somebody needs a pupper Avatar answered Sep 19 '22 03:09

uh oh somebody needs a pupper