ODR violation in ranges

Patrick Palka ppalka@redhat.com
Wed Mar 11 13:21:47 GMT 2020


On Wed, 11 Mar 2020, Tam S. B. via Gcc-patches wrote:

> IIUC using lambda in inline variable initializer is not ODR violation. This is covered in CWG 2300 ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1510r0.html#2300 ).
> 
> ________________________________________
> From: Libstdc++ <libstdc++-bounces@gcc.gnu.org> on behalf of Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org>
> Sent: Wednesday, March 11, 2020 10:26
> To: Nathan Sidwell
> Cc: libstdc++@gcc.gnu.org; GCC Patches
> Subject: Re: ODR violation in ranges
> 
> On 11/03/20 06:08 -0400, Nathan Sidwell wrote:
> >Jonathan,
> >the ranges header contains code like:
> >    inline constexpr __adaptor::_RangeAdaptorClosure all
> >      = [] <viewable_range _Range> (_Range&& __r)
> >      {
> > if constexpr (view<decay_t<_Range>>)
> >   return std::forward<_Range>(__r);
> > else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
> >   return ref_view{std::forward<_Range>(__r)};
> > else
> >   return subrange{std::forward<_Range>(__r)};
> >      };
> >
> >(line 1236)
> >
> >When you strip away all the templateyness, you have:
> >
> >
> >inline constexpr auto all = [] () {};
> >
> >
> >That's an ODR violation -- the initializers in different TUs are not
> >the same!
> >
> >As you can guess, I can't turn this into a header unit (well, I can,
> >but merging duplicates complains at you)
> 
> CC libstdc++@ and Patrick.
> 
> I did wonder if using lambdas for those global variables would be OK.
> 
> I think we'll need a new class template for each view adaptor, rather
> than using the _RangeAdaptorClosure to hold a closure.
> 
> Patrick, can you look into that please?

IIUC, it should suffice to replace the lambda in the initializer with a
function object, maybe something like:

  struct _All
  {
    constexpr auto
    operator()(...)
    {
    };
  };

  inline constexpr __adaptor::_RangeAdaptorClosure<_All> all;

Do the lambdas in the bodies of _RangeAdaptor::operator() and
_RangeAdaptorClosure::operator|() pose a problem too?



More information about the Gcc-patches mailing list