2012-06-21 16 views
6

是否可以在本地匿名函数中使用来自周围模板函数的模板类型参数?我敢肯定,我不能申报模板拉姆达...如何在lambda中使用模板类型参数?

例如,我怎么会去这样做这样的事情:

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,但我不想使用提升。

任何想法?

编辑:看来我错了,我认为问题是模板参数本身。相反,它是使用lambda函数编译的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()); 
+0

顺便说一句,错误消息似乎表明问题在于其他地方,特别是在* namespace * scope声明的lambda。 – Nawaz

+1

像这样'std :: not1(std :: function (fn))'铸造'fn'也可以。 –

回答

6

你当然可以使用T作为lambda表达式的参数类型。下面的程序汇编GCC 4.5.1罚款:

include <iostream> 

template<typename T> 
void f(T arg) 
{ 
    auto print = [](T a) { std::cout << a << std::endl; }; 
    print(arg); 
} 

int main() { 
     f(8899); 
     f("Nawaz"); 
     return 0; 
} 

见自己:http://ideone.com/l32Z6

BTW,错误消息似乎表明,问题出在其他地方,特别是lambda在命名空间中声明范围:

error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'


你的编辑后,所有我能说的是,不要然后使用std::not1。事实上,你甚至不需要它。你可以在lambda本身使用return !whatever-expression

+0

嗯......所以OP的错误是不是从lambda参数? – Jason

+0

@Jason:看起来就是这样。 – Nawaz

+0

Doh!我会更新问题。 – AJG85

2

编辑:作为@Nawaz指出的那样,你必须将错误形式来别的地方...我下面介绍的就是矫枉过正...

使用decltype,你可以做些什么如下所示:

template <typename T> 
void TrimString(std::basic_string<T>& str, 
       const std::locale& loc = std::locale(), 
       T arg = T()) 
{ 
    auto fn = [&loc](decltype(arg) c){ return std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); }; 

    //...rest of your code 
} 

这是通过使用(或滥用),表达decltype(arg)计算结果为arg类型的事实,在这种情况下是T的类型。

+0

为什么在'T'应该使用'decltype'应该可以正常工作?他也一定在做别的事情。 – Nawaz

+0

我假设他的错误来自于他所说的那样,那就是使用'T'而不是一个已知的参数类型......显然你的文章显示这是没有问题的...... – Jason

+0

如果我捕获' arg'并使用'decltype'我得到同样的错误。显然,如果我没有捕获它,那么它抱怨暗示捕获或没有默认捕获模式。这可能是沿着正确的路线,即使它不工作......或者MSVC被破坏,如果这应该工作。 – AJG85

9

问题不是由于在lambda内部使用模板参数引起的,因为参数在构建lambda时已经被解析为类型。

问题是您定义的lambda不能与std::not1合并,这需要作为参数std::unary_function<argument_type,return_type>

来解决这个问题最简单的方法是用鼠标右键在lambda表达式不使用std::not1,而是否定预测:

auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space,c); }; 

完整的代码编译,并与GCC 4.7.0,然后变成工作:

#include <string> 
#include <algorithm> 
#include <locale> 
#include <iostream> 

template <typename T> 
void TrimString(std::basic_string<T>& str, const std::locale& loc = std::locale()) 
{ 
    auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space,c); }; 

    str.erase(std::find_if(str.rbegin(), str.rend(),fn).base(), str.end()); 
    str.erase(str.begin(), std::find_if(str.begin(), str.end(), fn)); 
} 

int main() { 
    std::basic_string<char> s(" hello "); 
    TrimString(s); 
    std::cout << s << std::endl; 
    return 0; 
} 

此输出

hello 

如EXPE反恐执行局。

+0

是的,自己现在刚刚得出这个结论,我正在看实际问题! – AJG85

相关问题