2013-11-15 55 views
4

我在這裏看到了一些與在lambda中捕獲可變參數的gcc錯誤有關的問題。例如參見:Does lambda capture support variadic template argumentsCompiler bug, or non standard code? - Variadic template capture in lambda。我有什麼,我試圖做替代lambda捕獲的解決方法

#include <iostream> 
#include <functional> 

class TestVariadicLambda { 
public: 

    template<typename... Args> 
    std::function<void()> getFunc(Args... args) { 
     return [=]{ printArgs(args...); }; 
    } 

    template<typename T, typename... Args> 
    void printArgs(T value, Args... args) { 
     std::cout << value << ", "; 
     printArgs(args...); 
    } 

    void printArgs() {std::cout << "\n";} 
}; 

在GCC 4.8.2以下人爲的例子,我得到了以下錯誤:

../src/TestVariadicLambda.h: In lambda function: 
../src/TestVariadicLambda.h:9:25: error: parameter packs not expanded with ‘...’: 
    return [=]{ printArgs(args...); }; 
         ^
../src/TestVariadicLambda.h:9:25: note:   ‘args’ 
../src/TestVariadicLambda.h:9:29: error: expansion pattern ‘args’ contains no argument packs 
    return [=]{ printArgs(args...); }; 
         ^

我的問題是我怎麼解決這個,因爲它將無法在gcc4.8中工作

+0

它不會幫你很多,但代碼與叮噹3.4(中繼)。 – Ali

+0

我剛剛用g ++ 4.9快照測試過,它也在那裏工作。 –

+0

這是一個好消息,但不幸的是,如果你需要使用gcc 4.8 – Ali

回答

1

以下將工作。

#include <iostream> 
#include <functional> 
#include <vector> 

std::string to_string(const char* s) 
{ 
    return s; 
} 

class Test 
{ 
    private: 
     void print() {} 

    public: 
     template<typename T, typename... Args> 
     void print(T value, Args... args) 
     { 
      std::cout << value << "\n"; 
      print(args...); 
     } 

     template<typename... Args> 
     std::function<void()> getFunc(Args... args) 
     { 
      using namespace std; 
      std::vector<std::string> ArgumentList; 
      std::initializer_list<int> {(ArgumentList.push_back(to_string(args)), 0)...}; 
      return [=] {for (const auto &t : ArgumentList){print(t);}}; 
     } 
}; 

int main() 
{ 
    Test().getFunc("Hey", 1, 2, 3.0f)(); 
} 
+0

沒有靜態的解決方法? (即沒有std :: vector,但常規數組?) – GameDeveloper

0

下面是靜態的作品至少在GCC 4.8.0(應該也適用於VisualStudio中和鏗鏘以及)

(代碼大多來自this answer,我所做的元組包裝參數解決方法然後使用元組作爲旁路)

#include <iostream> 
#include <functional> 
#include <tuple> 
using namespace std; 

// ------------- UTILITY--------------- 
template<int...> struct index_tuple{}; 

template<int I, typename IndexTuple, typename... Types> 
struct make_indexes_impl; 

template<int I, int... Indexes, typename T, typename ... Types> 
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...> 
{ 
    typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type; 
}; 

template<int I, int... Indexes> 
struct make_indexes_impl<I, index_tuple<Indexes...> > 
{ 
    typedef index_tuple<Indexes...> type; 
}; 

template<typename ... Types> 
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...> 
{}; 


template<class Ret, class... Args, int... Indexes > 
Ret apply_helper(Ret (*pf)(Args...), index_tuple<Indexes...>, tuple<Args...>&& tup) 
{ 
    return pf(forward<Args>(get<Indexes>(tup))...); 
} 

template<class Ret, class ... Args> 
Ret apply(Ret (*pf)(Args...), const tuple<Args...>& tup) 
{ 
    return apply_helper(pf, typename make_indexes<Args...>::type(), tuple<Args...>(tup)); 
} 

template<class Ret, class ... Args> 
Ret apply(Ret (*pf)(Args...), tuple<Args...>&& tup) 
{ 
    return apply_helper(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup)); 
} 



/// ------------------- REAL CODE -------- 

void printArgs() {std::cout << "\n";} 

template<typename T, typename... Args> 
void printArgs(T value, Args... args) { 
    std::cout << value << ", "; 
    printArgs(args...); 
} 

template<typename... Args> 
std::function<void()> getFunc(Args... args) { 
    std::tuple<Args...> tup(args...); 
    return [=]{ apply<void, Args...>(printArgs, tup); }; 
} 


int main(){ 
    auto f = getFunc<int,float,const char*>(4,5.4f,"hello"); 
    f(); 
    return 0; 
} 

另外爲什麼你不使用std :: bind?基本上std :: bind可以爲你的參數創建一個lambda(只是語法糖,爲你選擇最可行的方式:))

+0

編譯(並運行)良好的GCC 4.7 +鏗鏘3.3+和Visual Studio 2013更新3 – GameDeveloper

相關問題