0

There are many articles here about variadic generic lambda functions, however I would like a simple explanation on how to access an argument inside the lambda function

pt. I am using an old setup to fetch the arguments, however I want a more generic solution

example - old use :

auto lambda = [](...)                              
{                                                  
    va_list args;                                  
    va_start(args,0);                              
    auto b = va_arg(args, const char*);            
    cout << "hello " << b << endl;           
    va_end(args);                                  
};                                                 

lambda();                                      
lambda("world");                                 

shows this:

hello
hello world

I would like to know if it is possible to use variadic template on lambda functions to refactor this into are more generic solution

also how to access individual arguments inside the lambda, not just all in one go

serup
  • 3,676
  • 2
  • 30
  • 34

2 Answers2

2

Here is what I ended up with:

auto lambda = [](const auto&...args)                                  
{                                                                      
    typedef boost::variant<int, float, std::string> Variant;           
    std::vector<Variant> vec = {args...};                              
    std::cout << "hello ";                                             
    for(auto a: vec) {                                                 
        std::cout << a;                                                
    }                                                                  
    std::cout << std::endl;                                            
};                                                                     

lambda("world", " and ", "universe");     

shows following:

hello world and universe

it seems using a Variant type for vector, does the magic

serup
  • 3,676
  • 2
  • 30
  • 34
1

You may do something like:

auto lambda = [](const auto&...args)
{
    std::cout << "hello ";
    const int dummy[] = {0, ((std::cout << args), 0)...};
    static_cast<void>(dummy);
    std::cout << std::endl;
};

or with folding expression in C++17:

auto lambda = [](const auto&...args)
{
    (std::cout << "hello " << ... << args) << std::endl;
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I have seen this part `const int dummy[] = {0, ((std::cout << args), 0)...};` however I really do not understand what is happening there - could you elaborate on this? – serup Jan 27 '17 at 11:27
  • 1
    @serup: You may look at [how-to-iterate-over-a-stdtuple-in-c-11](http://stackoverflow.com/questions/26902633/how-to-iterate-over-a-stdtuple-in-c-11) – Jarod42 Jan 27 '17 at 11:33
  • waou - you really saved my day - top rank to you – serup Jan 27 '17 at 11:46
  • I could not get the C++17 version to work - how would you write your makefile for this ? must be something wrong with mine – serup Jan 27 '17 at 12:04
  • it seems that in combination with this solution and following http://stackoverflow.com/a/7232968/3990012 a more complete solution can be made – serup Jan 27 '17 at 13:36
  • @serup, Compile with `-std=c++1z` or `-std=c++17` if the compiler supports it and make sure you're using a compiler that implements fold expressions. There's also no need for that `any` (which is actually a variant). It won't get you anything extra for simply iterating over arguments. In fact, it limits the function's usefulness because it no longer works for any type of argument that you can print, only the few types you specify. – chris Jan 27 '17 at 15:24
  • @chris, I tried adding both -std=c++1y and -std=c++17 and it still gave compiler error, also I think maybe I need to read a little more about folding before I start using it – serup Jan 30 '17 at 08:21