2012-06-21 17 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

相關問題