Another potential hole in the tuple specs

View: New views
10 Messages — Rating Filter:   Alert me  

Another potential hole in the tuple specs

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

Here's another potential problem with the tuple spec.  The latest draft
declares std::ignore like so:
 
        namespace std {
            const /*unspecified*/ ignore;
        }
 
The type of std::ignore is implementation-defined but for illustration,
let's say its defined like this:

        namespace std {

        struct _Ignore
        {
            template <class _Type>
            _Ignore& operator= (const _Type& value) { return *this; }
        };

        const _Ignore ignore = _Ignore ();

        } // namespace std

(The need for the operator will become evident shortly.)

Here's how the tie() function is specified, quoting from the standard:

          template<class... Types}
          tuple<Types&...> tie(Types&... t);

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

        5 [ Example: tie functions allow one to create tuples that
unpack tuples into variables. ignore can be used for
            elements that are not needed:

                int i; std::string s;
                tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
                // i == 42, s == "C++"

          -end example ]

In the example, the return type of the call to the tie() function is
std::tuple<int&, const std::_Ignore&, std::string&>.  Note that the
second element type in the tuple is a constant reference.  Regardless of
the implementation-defined type of std::ignore, isn't it impossible to
change the value of a constant reference once initialized?  This would
mean the example shown above is ill-formed I believe.

Brad.

Re: Another potential hole in the tuple specs

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
> Here's another potential problem with the tuple spec.  The latest draft
> declares std::ignore like so:
>  
> namespace std {
>    const /*unspecified*/ ignore;
> }
>  
> The type of std::ignore is implementation-defined but for illustration,
> let's say its defined like this:
>
> namespace std {
>
> struct _Ignore
> {
>    template <class _Type>
>    _Ignore& operator= (const _Type& value) { return *this; }
> };
>
> const _Ignore ignore = _Ignore ();
>
> } // namespace std
>
> (The need for the operator will become evident shortly.)
>
> Here's how the tie() function is specified, quoting from the standard:
>
>  template<class... Types}
>  tuple<Types&...> tie(Types&... t);
>
> 4 Returns: tuple<Types&>(t...). When an argument in t is ignore,
> assigning any value to the corresponding
>  tuple element has no effect.
>
> 5 [ Example: tie functions allow one to create tuples that
> unpack tuples into variables. ignore can be used for
>    elements that are not needed:
>
> int i; std::string s;
> tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
> // i == 42, s == "C++"
>
>  -end example ]
>
> In the example, the return type of the call to the tie() function is
> std::tuple<int&, const std::_Ignore&, std::string&>.  Note that the
> second element type in the tuple is a constant reference.  Regardless of
> the implementation-defined type of std::ignore, isn't it impossible to
> change the value of a constant reference once initialized?  This would
> mean the example shown above is ill-formed I believe.

You mean because tie(i, ignore, s) = make_tuple(42, 3.14, "C++")
must assign 3.14 to std::ignore? Would declaring the assignment
operator cost be a way to make it work?

Martin



RE: Another potential hole in the tuple specs

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:msebor@...] On Behalf Of Martin Sebor
> Sent: Monday, July 07, 2008 5:44 PM
> To: dev@...
> Subject: Re: Another potential hole in the tuple specs
>
> Eric Lemings wrote:
> >  
> >
> > Here's another potential problem with the tuple spec.  The
> latest draft
> > declares std::ignore like so:
> >  
> > namespace std {
> >    const /*unspecified*/ ignore;
> > }
> >  
> > The type of std::ignore is implementation-defined but for
> illustration,
> > let's say its defined like this:
> >
> > namespace std {
> >
> > struct _Ignore
> > {
> >    template <class _Type>
> >    _Ignore& operator= (const _Type& value) { return *this; }
> > };
> >
> > const _Ignore ignore = _Ignore ();
> >
> > } // namespace std
> >
> > (The need for the operator will become evident shortly.)
> >
> > Here's how the tie() function is specified, quoting from
> the standard:
> >
> >  template<class... Types}
> >  tuple<Types&...> tie(Types&... t);
> >
> > 4 Returns: tuple<Types&>(t...). When an argument in t is ignore,
> > assigning any value to the corresponding
> >  tuple element has no effect.
> >
> > 5 [ Example: tie functions allow one to create tuples that
> > unpack tuples into variables. ignore can be used for
> >    elements that are not needed:
> >
> > int i; std::string s;
> > tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
> > // i == 42, s == "C++"
> >
> >  -end example ]
> >
> > In the example, the return type of the call to the tie() function is
> > std::tuple<int&, const std::_Ignore&, std::string&>.  Note that the
> > second element type in the tuple is a constant reference.  
> Regardless of
> > the implementation-defined type of std::ignore, isn't it
> impossible to
> > change the value of a constant reference once initialized?  
> This would
> > mean the example shown above is ill-formed I believe.
>
> You mean because tie(i, ignore, s) = make_tuple(42, 3.14, "C++")
> must assign 3.14 to std::ignore? Would declaring the assignment
> operator cost be a way to make it work?

A const assignment operator?  Sounds unorthodox but I'll try it out.

My current workaround is to declare std::ignore mutable (i.e.
non-const).  A const assignment operator (if it works) would be
preferable; no visible workaround required.

Brad.

Re: Another potential hole in the tuple specs

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:
>  
[...]
> A const assignment operator?  Sounds unorthodox but I'll try it out.
>
> My current workaround is to declare std::ignore mutable (i.e.
> non-const).  A const assignment operator (if it works) would be
> preferable; no visible workaround required.

Remember that even the absence (or presence) of the const
qualifier on things like std::ignore can be detected by
conformance test suites so dropping it is not a viable
option.

Martin

RE: Another potential hole in the tuple specs

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:sebor@...]
> Sent: Tuesday, July 08, 2008 10:52 AM
> To: dev@...
> Subject: Re: Another potential hole in the tuple specs
>
> Eric Lemings wrote:
> >  
> [...]
> > A const assignment operator?  Sounds unorthodox but I'll try it out.
> >
> > My current workaround is to declare std::ignore mutable (i.e.
> > non-const).  A const assignment operator (if it works) would be
> > preferable; no visible workaround required.
>
> Remember that even the absence (or presence) of the const
> qualifier on things like std::ignore can be detected by
> conformance test suites so dropping it is not a viable
> option.

Assuming the draft standard is actually correct, that is.  In this case,
I don't think there is any real need for std::ignore to be a constant
really.  (Thinking about asking whether std::ignore really needs to be a
constant on the committee reflector.)

I tried making std::ignore const and adding const to the internal
assignment operator.  I also tried adding overloads for const and
non-const assignment.  Still got errors in all cases.

The only other recourse I can think of is to use remove_const on the
element types where appropriate.

Brad.

Re: Another potential hole in the tuple specs

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Eric Lemings wrote:

>  
>
>> -----Original Message-----
>> From: Martin Sebor [mailto:sebor@...]
>> Sent: Tuesday, July 08, 2008 10:52 AM
>> To: dev@...
>> Subject: Re: Another potential hole in the tuple specs
>>
>> Eric Lemings wrote:
>>>  
>> [...]
>>> A const assignment operator?  Sounds unorthodox but I'll try it out.
>>>
>>> My current workaround is to declare std::ignore mutable (i.e.
>>> non-const).  A const assignment operator (if it works) would be
>>> preferable; no visible workaround required.
>> Remember that even the absence (or presence) of the const
>> qualifier on things like std::ignore can be detected by
>> conformance test suites so dropping it is not a viable
>> option.
>
> Assuming the draft standard is actually correct, that is.
> In this case,
> I don't think there is any real need for std::ignore to be a constant
> really.  (Thinking about asking whether std::ignore really needs to be a
> constant on the committee reflector.)

IMO, there is no need for it not to be, and being constant
is more efficient than not (can be stored in ROM).

>
> I tried making std::ignore const and adding const to the internal
> assignment operator.  I also tried adding overloads for const and
> non-const assignment.  Still got errors in all cases.
>
> The only other recourse I can think of is to use remove_const on the
> element types where appropriate.

ignore is declared const in Boost so there must be a way
to implement tie() without declaring the object non-const.

Martin

RE: Another potential hole in the tuple specs

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Martin Sebor [mailto:sebor@...]
> Sent: Tuesday, July 08, 2008 1:14 PM
> To: dev@...
> Subject: Re: Another potential hole in the tuple specs
>
> Eric Lemings wrote:
> >  
> >
...

> >
> > I tried making std::ignore const and adding const to the internal
> > assignment operator.  I also tried adding overloads for const and
> > non-const assignment.  Still got errors in all cases.
> >
> > The only other recourse I can think of is to use remove_const on the
> > element types where appropriate.
>
> ignore is declared const in Boost so there must be a way
> to implement tie() without declaring the object non-const.

Found it.  Thanks.

Brad.

RE: Another potential hole in the tuple specs

by Travis Vitek-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

Eric Lemings wrote:

>
>> Martin Sebor wrote:
>>
>> Eric Lemings wrote:
>> >  
>> [...]
>> > A const assignment operator?  Sounds unorthodox but I'll
>> > try it out.
>> >
>> > My current workaround is to declare std::ignore mutable (i.e.
>> > non-const).  A const assignment operator (if it works) would be
>> > preferable; no visible workaround required.
>>
>> Remember that even the absence (or presence) of the const
>> qualifier on things like std::ignore can be detected by
>> conformance test suites so dropping it is not a viable
>> option.
>
>Assuming the draft standard is actually correct, that is.  In
>this case, I don't think there is any real need for std::ignore
>to be a constant really.  (Thinking about asking whether
>std::ignore really needs to be a constant on the committee
>reflector.)

I could agree that it shouldn't _need_ to be const given that it needs
no member data and it is just a placeholder type. But I'd be willing to
bet that this was an intentional design decision.

>
>I tried making std::ignore const and adding const to the internal
>assignment operator.  I also tried adding overloads for const and
>non-const assignment.  Still got errors in all cases.

The following testcase works just fine (on acc-6.16, gcc-4.3.1 &
msvc-8.0)

  namespace std {


  struct _Ignore
  {
      template <class _TypeT>
      void operator=(const _TypeT&) const
      {
      }
  };

  // should make this extern and define in a .cpp
  const _Ignore ignore = std::_Ignore ();


  } // namespace std



  int main ()
  {
      std::ignore = 1;
      std::ignore = 1.f;

      std::ignore = std::ignore;
      std::ignore = (void (*)(int))0;

      return 0;
  }

Perhaps you could post the error and a testcase?

>
>The only other recourse I can think of is to use remove_const on the
>element types where appropriate.

I'm sure the above strategy will work.

>
>Brad.
>

RE: Another potential hole in the tuple specs

by Eric Lemings-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

 

> -----Original Message-----
> From: Travis Vitek [mailto:Travis.Vitek@...]
> Sent: Tuesday, July 08, 2008 2:36 PM
> To: dev@...
> Subject: RE: Another potential hole in the tuple specs
>
>  
...

> The following testcase works just fine (on acc-6.16, gcc-4.3.1 &
> msvc-8.0)
>
>   namespace std {
>
>
>   struct _Ignore
>   {
>       template <class _TypeT>
>       void operator=(const _TypeT&) const
>       {
>       }
>   };

This would probably work also.  In any case, I've got it working now.

I'm currently enhancing the tuple test suite and doing more extensive
testing.

Brad.

Re: Another potential hole in the tuple specs

by Martin Sebor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Travis Vitek wrote:
>  
[...]

>> I tried making std::ignore const and adding const to the internal
>> assignment operator.  I also tried adding overloads for const and
>> non-const assignment.  Still got errors in all cases.
>
> The following testcase works just fine (on acc-6.16, gcc-4.3.1 &
> msvc-8.0)
>
>   namespace std {
>
>
>   struct _Ignore
>   {
>       template <class _TypeT>
>       void operator=(const _TypeT&) const
>       {
>       }

FWIW, unless the latest working paper specifies this assignment
operator I would expect there to be other viable techniques to
accomplish the same effect, such as defining our own template,
say, __rw_assign_tuple_elem(), to do the assignment, and
providing a no-op const __rw_ignore& overload.

I'm not suggesting we make use of this technique, just pointing
out that there likely are a number of other solutions that don't
require making std::ignore non-const.

Martin
LightInTheBox - Buy quality products at wholesale price