[Boost-bugs] [Boost C++ Libraries] #12754: operator| overload for boost::range_details::replace_holder is not SFINEA friendly

Subject: [Boost-bugs] [Boost C++ Libraries] #12754: operator| overload for boost::range_details::replace_holder is not SFINEA friendly
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2017-01-12 13:40:13


#12754: operator| overload for boost::range_details::replace_holder is not SFINEA
friendly
-----------------------------------------------+------------------------
 Reporter: Tim Wynants <tim.wynants+boost@…> | Owner: neilgroves
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: range
  Version: Boost 1.61.0 | Severity: Problem
 Keywords: SFINEA, ADL |
-----------------------------------------------+------------------------
 If I provide a simple operator | overload for my template class and I
 provide a class template specializations with for instance a boost range
 (so that adl adds the boost::range_details namespace for overloads) then
 the compiler chokes on the non-SFINEA friendly overload

 {{{
 friendly boost::range_details::operator|(
     SinglePassRange,
     const replace_holder<BOOST_DEDUCED_TYPENAME
 range_value<SinglePassRange>::type> )
 }}}


 ----
 Example:


 {{{
 namespace local
 {
     template<typename T>
     struct boo {};

     // this overload is not prefered when T is a boost::range::xxx_range
     template<typename T, typename U>
     auto operator|(boo<T>, U)
     {
         return false;
     }

     void finds_local_operator_overload()
     {
         std::vector<int> xs;

         // works like expected and calls local::operator|
         auto f = boo<decltype(xs)>{} | xs;
     }

     void
 prefers_boost_range_detail_replaced_operator_overload_instead_of_local_operator()
     {
         std::vector<int> xs;
         // compiler error because it tries to call
 'boost::range_detail::operator|'
         auto filtered = xs | boost::adaptors::filtered([](auto &&x){
 return x % 2; });
         auto f = boo<decltype(filtered)>{} | xs;
     }
 }
 }}}




 clang error (msvc reports almost the same):


 {{{
 /xxx/../../thirdparty/boost/1.60.0/dist/boost/range/value_type.hpp:26:70:
 error: no type named 'type' in
 'boost::range_iterator<local::boo<boost::range_detail::filtered_range<(lambda
 at
       /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >,
 void>'
     struct range_value : iterator_value< typename range_iterator<T>::type
>
                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
 /xxx/../../thirdparty/boost/1.60.0/dist/boost/range/adaptor/replaced.hpp:122:40:
 note: in instantiation of template class
 'boost::range_value<local::boo<boost::range_detail::filtered_range<(lambda
 at
       /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >
>' requested
       here
                BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>&
 f)
                                        ^
 /xxx/Tests.cpp:222:37: note: while substituting deduced template arguments
 into
       function template 'operator|' [with SinglePassRange =
 local::boo<boost::range_detail::filtered_range<(lambda at
       /xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >]
         auto f = boo<decltype(filtered)>{} | xs;
 }}}


 This can be easily prevented by making the operator overload SFINEA
 friendly.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12754>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:20 UTC