Is it possible to use a template type argument from a surrounding template function within a local anonymous function? I'm pretty certain I can't declare a template lambda ...
For example how would I go about doing 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)));
}
Currently this generates the following error:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
Which makes sense as the lambda has no clue about argument T from the surrounding template function.
I use VS2010 and gcc 4.7 but I don't want to use boost.
Any ideas?
Edit: It appears I was wrong in my assumption that the problem was the template argument itself. Rather it is the use of std::not1 being compiled with the lambda function. Here is the more verbose 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 the type for the argument if it's a function type? I'm not sure what I'm doing wrong still ...
Answers:
Option 1: If I don't use std::not1 and instead negate the returned value in the lambda I get the same behavior without issue.
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
Option 2: Since the lambda is not longer equivalent to how std::isspace would behave as a unary predicate a function object constructor cast also does the trick.
str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::function<bool(T)>(fn))).base(), str.end());
fnlike thisstd::not1(std::function<bool(char)>(fn))also works.