Можно ли использовать аргумент типа шаблона из окружающей функции шаблона внутри локальной анонимной функции? Я почти уверен, что не могу объявить шаблонную лямбду...
Например, как мне сделать что-то вроде этого:
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)));
}
В настоящее время это генерирует следующую ошибку:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
Что имеет смысл, поскольку лямбда понятия не имеет об аргументе T
из окружающей шаблонной функции.
Я использую VS2010 и gcc 4.7, но не хочу использовать boost.
Есть идеи?
Редактировать: Похоже, я ошибся в своем предположении, что проблема заключалась в самом аргументе шаблона. Скорее это использование std::not1
, компилируемого с лямбда-функцией. Вот более подробный вывод об ошибке:
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>
]
Нужно ли явно объявлять тип аргумента, если это тип функции? Я все еще не уверен, что я делаю неправильно ...
Ответы:
Вариант 1: Если я не использую std::not1
и вместо этого инвертирую возвращаемое значение в lambda я получаю такое же поведение без проблем.
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
Вариант 2: Поскольку лямбда больше не эквивалентна тому, как std::isspace
будет вести себя как унарный предикат, приведение конструктора функционального объекта также помогает.
str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::function<bool(T)>(fn))).base(), str.end());