[Boost-bugs] [Boost C++ Libraries] #4540: fold<Sequence>() instantiates result_of::fold<Sequence const>

Subject: [Boost-bugs] [Boost C++ Libraries] #4540: fold<Sequence>() instantiates result_of::fold<Sequence const>
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2010-08-13 15:34:39


#4540: fold<Sequence>() instantiates result_of::fold<Sequence const>
-------------------------------------+--------------------------------------
 Reporter: anonymous | Owner: djowel
     Type: Bugs | Status: new
Milestone: Boost 1.44.0 | Component: fusion
  Version: Boost Development Trunk | Severity: Problem
 Keywords: |
-------------------------------------+--------------------------------------
 Hi,

 this is a complicated one, I'll try my best:

 there is a problem with fold() and maybe other fusion functions whose
 result is computed from the result type of user functors.

 in iteration/detail/fold.hpp, there are two fold()'s, the default one and
 a specialization for const sequences:
 {{{
     inline typename result_of::fold<Seq const,State const,F>::type
     BOOST_FUSION_FOLD_NAME(Seq const& seq,State const& state,F f)
 }}}
 I'm not sure why it is there since there isn't any difference to the non-
 const fold().
 but the fact that it is there causes problems when using fold() with a
 non-const sequence:

 {{{
     fusion::vector<int> vec;
     fusion::fold(vec,0,F());
 }}}
 even though the sequence is not const, at least MSVC (and I vaguely
 remember something about that in the C++ standard) instantiates all result
 types of the function overload set, before the arguments are matched to
 the non-const fold().

 ==> fusion::result_of::fold<Sequence '''const''',State,F> is instantiated.

 under normal circumstances this only constitutes an unnecessary
 instantiation, but when the result type depends on user functors it can
 cause instantiatiation of undefined types.

 for example:
 {{{
 struct F{
     template<typename Args>
     struct result;
     int operator()(int state,int &element) const{
         return state;
     }
 };

 template<typename State>
 struct F::result<F(State,int &)>{
     typedef int type;
 };

 int main(){
     fusion::vector<int> vec;
     fusion::fold(vec,0,F());
 }
 }}}

 the result type of F is only defined for argument type "int &", which is
 enough for this fold. but the call to fold() instantiates the ''const''
 specialization of fold(), and therefore instantiates
 result_of::fold<vector '''const'''>, which instantiates the result type of
 F(State,int const &) ==> compiler error

 when the following code snippet is added as a workaround, it works:

 {{{
 template<typename State>
 struct F::result<F(State,int const &)>{
     typedef int type;
 };
 }}}

 bottom line - the const specialization of fold() probably shouldn't be
 there.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/4540>
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:04 UTC