Is it possible to use a template type argument from the surrounding template function in a local anonymous function? I am sure that I cannot declare a lambda pattern ...
For example, how could I do something like this:
template <typename T> void TrimString(std::basic_string<T>& str, const std::locale& loc = std::locale()) { // std::isspace as lambda unary predicate? auto fn = [&loc](T c){ return std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); }; // trim right str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(fn)).base(), str.end()); // trim left str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not1(fn))); }
This currently creates the following error:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
Which makes sense since lambda has no idea about the argument T
from the surrounding template function.
I am using VS2010 and gcc 4.7, but I do not want to use boost.
Any ideas?
Edit: It seems like I was mistaken in my assumption that the problem was itself a template argument. Rather, it is using std::not1
compiled using a lambda function. Here is a more detailed error output:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>' : see declaration of '`anonymous-namespace'::<lambda0>' : see reference to class template instantiation 'std::unary_negate<_Fn1>' being compiled with [ _Fn1=`anonymous-namespace'::<lambda0> ] : see reference to function template instantiation 'void TrimString<char>(std::basic_string<_Elem,_Traits,_Ax> &,const std::locale &)' being compiled with [ _Elem=char, _Traits=std::char_traits<char>, _Ax=std::allocator<char> ]
Do you need to explicitly declare an argument type if it is a function type? I'm not sure what I'm doing wrong yet ...
Answers:
Option 1: If I do not use std::not1
and instead deny the return value in lambda, I get the same behavior without problems.
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
Option 2: Since lambda is no longer equivalent to how std::isspace
behaves like a unary predicate, the object constructor object object also does the trick.
str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::function<bool(T)>(fn))).base(), str.end());