Is libstdc ++ incorrect to reject the purpose of volatile rvalue in std :: ignore?

I noticed that the libstdC ++ std::ignore implementation takes a const T& argument, which cannot be bound to the mutable rvalue value. Therefore, the following code does not 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 a violation of the standard or is there a sentence that displays this behavior undefined?

+8
c ++ language-lawyer c ++ 11 g ++ tuples
source share
2 answers

I am not a language lawyer, so I am going to answer this question as best as possible.

ignore is on the tuple resume in tuple.general as such:

 // [tuple.creation], tuple creation functions: const unspecified ignore; 

As you noticed, the libstdc ++ implementation defines ignore as follows:

  // 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; } }; 

While the libC ++ version defines it as follows:

 template <class _Up> struct __ignore_t { template <class _Tp> _LIBCPP_INLINE_VISIBILITY const __ignore_t& operator=(_Tp&&) const {return *this;} }; 

Thus, it compiles in libC ++. Now the definition of std::tie can be found in [tuple.creation], which says:

Returns: tuple<Types&...>(t...) . When the argument in t is ignore , assigning any value to the corresponding element of the tuple, no effect.

This doesn't say anything about ignore , so I'm going to do this before unspecified behavior. You can claim this behavior is undefined by omission, but it can stretch it.

0
source share

A comment:

 // g++ 4.8.4 int main() { volatile int vi; std::ignore = vi; // error: no match for 'operator=' ( // operand types are 'const std::_Swallow_assign' // and 'std::remove_reference<volatile int&>::type {aka volatile int}' // ) // std::ignore = std::move(vi); // However this compiles: volatile int&& vir = std::move(vi); std::ignore = vir; } 
0
source share

All Articles