a1c2e83d   
   From: daniel.kruegler@googlemail.com   
      
   Am 18.05.2012 15:03, schrieb Mark Summerfield:   
   > Is what I'm trying to do very much against the grain of C++11? Or is   
   > it that I'm taking the wrong approach?   
   >   
   > Scenario: I have validator functions that take a string and return   
   > an object of a given type, e.g., int validator(string); string   
   > validator(string); bool validator(string) --- or throws if the   
   > string can't be converted to the required type (e.g., for int the   
   > string doesn't represent a number or is too big or too small). These   
   > work fine. But I also want to create a validator that takes an   
   > existing validator plus a collection of specific values and returns   
   > a new validator that does the conversion (or throws) and if it   
   > hasn't thrown then checks to see if the converted item is in the   
   > collection.   
      
   I'm not sure what you are asking for. It seems that your function   
   template makeSetValidator does what you want to realize. You seem to   
   have some assumptions about template deduction that aren't valid,   
   though, for details see below.   
      
   > I changed the code along the lines you suggested:   
   >   
   > template   
   > struct identity { typedef T type; };   
   > template   
   > using NonDeduced = typename identity::type;   
   >   
   > template   
   > using Validator = std::function;   
      
   Btw.: I wasn't suggestion to change your signature T(const   
   std::string&) to T(const std::string).   
      
   > template   
   > Validator   
   > makeSetValidator(const C&validItems,   
   > NonDeduced>   
   > validate)   
   > {   
   > return [=](const std::string s)->typename C::value_type{   
   > const auto x = validate(s);   
      
   Just as a remark: Your previous form binding the result of the   
   validate call by reference was valid, because the reference is   
   life-time extended. But I think your new code is more idomatic than   
   before (There is no real advantage of binding to a reference and such   
   code is questionable at best).   
      
   > if (std::find(std::begin(validItems), std::end(validItems), x)   
   > != std::end(validItems))   
   > return x;   
   > throw ValueError("Invalid item '" + s + "'");   
   > };   
   > }   
   >   
   > I also tried changing the call site:   
   >   
   > auto v = makeSetValidator(std::set{-4, 8, 31}, validate);   
   >   
   > But g++ 4.7.0 gave me this:   
      
   The error is understandable. It becomes easier to understand this,   
   when you simplify your example to the following form:   
      
   Validator v = validate;   
      
   I expect the same kind of error here. The problem is easy to   
   understand: As defined, the template parameter of validate cannot be   
   deduced without further information. A possible way to provide this   
   context information is to specify the *exact* function pointer type,   
   like so:   
      
   int(*p)(const std::string&) = validate;   
      
   But std::function is not function pointer type, nor is it a type   
   that requires a special function pointer of function type X. It   
   accepts any form of Callable type that is "compatible" with the   
   function type X, especially conversions of the parameter types of X or   
   of the return type of X are all supported. The relevant constructor of   
   std::function is this one:   
      
   template function::function(F);   
      
   Note that this is also a template, so we have a catch-22 situation here:   
   You want to have the return type of template validate deduced given a   
   template that needs the necessary information to deduce template   
   parameter F here.   
      
   I see no way except that you somehow specify the return type of   
   validate as in your original form. Alternatively you could provide a   
   further overload of makeSetValidator that accepts a special function   
   pointer type, like so:   
      
   template   
   Validator   
   makeSetValidator(const C& validItems,   
    NonDeduced validate);   
      
   with the same definition as your current definition. (Above form   
   assumes that your validate function has the following declaration   
      
   template   
   T validate(const std::string &s);   
      
   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)   
|