From: daniel.kruegler@googlemail.com   
      
   On 2012-03-22 01:26, Andy Champ wrote:   
   [..]   
   >> There are basically two ways to make this work. I'm starting with that   
   >> one, which demonstrates the root of your problem here. It bases on an   
   >> idiom to make the parameter Item non-deducible in   
   >> std::function. Just define   
   >>   
   >> template   
   >> struct identity { typedef T type; };   
   >>   
   >>   
   >> and rewrite for_each_in to:   
   >>   
   >> template    
   >> void for_each_in(   
   >> std::vector- & vec,   
   >> std::function::type&)> functor)   
   >> {   
   >> std::for_each(vec.begin(), vec.end(), functor);   
   >> }   
   >>   
   >   
   > OK, I see. it's taken me a couple of minutes though. I think I'd have   
   > trouble in the code review. it's also putting a new type "identity" into   
   > the namespace, which I'd prefer to avoid - but that name is completely   
   > arbitrary, so can be as mangled as I like.   
      
   This is correct. In theory I could have used std::common_type instead   
   of identity, for example. Personally I find the simpler template   
   identity used in this idiom easier to understand.   
      
   It may be worth to consider to standardize the following as a useful   
   C++11 idiom taking advantage of an alias template:   
      
   template   
   using non_deduced = typename identity::type;   
      
   and then using only the alias in your declarations:   
      
   template    
   void for_each_in(std::vector
- & vec,   
   std::function&)> functor);   
      
   This looks pretty much readable to me and is hopefully self-explaining.   
      
   >> A much simpler solution in your example is to give up the dependency to   
   >> std::function in for_each_in (From your code there is no obvious reason   
   >> for this) and to write instead:   
   >>   
   >> template    
   >> void for_each_in(   
   >> std::vector
- & vec,   
   >> F functor)   
   >> {   
   >> std::for_each(vec.begin(), vec.end(), functor);   
   >> }   
   >>   
   >   
   > ... and that's the way I think I'll end up doing it.   
   >   
   > I think this removes any link between the types of F and of Item, beyond   
   > that the type of the iterator's target is going to be compatible in some   
   > way with the type of the parameter in the lambda, but I can live with   
   > it. Experimentation shows me I had that problem anyway.   
      
   It is possible to combine the advantages of both worlds by making your   
   second for a constrained template. First introduce a reusable trait   
   is_callable e.g. like so:   
      
   #include    
      
   template   
   typename std::add_rvalue_reference::type declval();   
   // Unless I'm mistaken, VC10 does not provide std::declval as it should   
      
   template   
   struct is_callable_impl {   
    template   
    static auto test(int) -> decltype((void)   
   declval()(declval()), std::true_type());   
    template   
    static auto test(...) -> std::false_type;   
    typedef decltype(test(0)) type;   
   };   
      
   template   
   struct is_callable : is_callable_impl::type {};   
      
   After this declare your template as follows:   
      
   template    
   typename std::enable_if::value>::type   
   for_each_in_3(std::vector
- & vec, F functor);   
      
   > Now tell me - is half past four the normal time you start work in Germany?   
      
   No.   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|