2016-11-22 4 views
4

Я видел, как объявить вектор функций (см. calling a function from a vector).Как объявить вектор функций (lambdas)

Но это отвечает указателям пользователей. Как создать вектор функций/lambdas, используя новый синтаксис в современном C++?

примеры функций с использованием нового синтаксиса обычно используют авто:

auto f = [] (std::string msg) -> void { 
    std::cout << msg << std::endl; 
}; 

Что фактический тип F? поэтому я могу объявить вектор этого типа?

большое спасибо за любую помощь

+2

"* Что фактический тип F *?" Unnameable. "*, поэтому я могу объявить вектор этого типа? *« Да, но это не помогло, потому что lambdas не являются стандартными по умолчанию. 'std :: vector >' вероятно, подойдет вашим целям. – ildjarn

+2

вы действительно можете использовать указатели, если лямбда не имеет замыканий, btw – vu1p3n0x

+1

Если вам не нужен вектор (т. Е. Если фактические лямбды известны во время компиляции), вы можете создать std :: tuple lambdas. – dats

ответ

10

Использование std::function с соответствующим типом:

std::vector<std::function<void(void)>> vec; 
vec.push_back([]()->void{}); 

В вашем случае это будет std::function<void(std::string)>.

Точный тип лямбда не имеет смысла в соответствии со стандартом ([expr.prim.lambda]/3):

тип лямбда-выражения (который также является тип объекта замыкания) является уникальным, неназванный несрастание типа класса

+0

Спасибо. Это именно то, что я искал. – dmg

+4

Другой вариант - использовать указатели функций, если лямбды не имеют захватов. – rubenvb

7

Что фактический тип f? поэтому я могу объявить вектор этого типа?

Тип f может быть выведен только с помощью auto. Вы можете объявить vector этого типа с использованием

std::vector<decltype(f)> v; 

Однако, это не очень полезно. Лямбда-функции, которые кажутся поразительно похожими, имеют разные типы. Хуже того, функции лямбда, имеющие одинаковое тело, также имеют разные типы.

auto f = [] (std::string msg) -> void { 
    std::cout << msg << std::endl; 
}; 

auto g = [] (std::string msg) -> void { 
    std::cout << msg << std::endl; 
}; 

auto h = [] (std::string msg) -> void { 
    std::cout << msg << '+' << msg << std::endl; 
}; 

Учитывая вышеперечисленные функции, вы не можете использовать

std::vector<decltype(f)> v; 
v.push_back(f); // OK 
v.push_back(g); // Not OK 
v.push_back(h); // Not OK 

Ваш лучший вариант заключается в создании std::vector из std::function с. Вы можете добавить лямбда-функции к этому std::vector. С учетом приведенных выше определений f и g, вы можете использовать:

std::vector<std::function<void(std::string)>> v; 
v.push_back(f); 
v.push_back(g); 
v.push_back(h); 
0

Как уже упоминалось каждый лямбда Вы заявляете имеет уникальный контекст определенного типа, даже если она имеет, казалось бы, идентичные подписи. Вот почему вектор лямбда имеет только теоретическое значение - вы могли бы проталкивать туда не более одной лямбда ...У вас есть два варианта: вы можете согласиться с предложенным подходом из других ответов и сохранить лямбда в стирание типа std::function перед тем, как положить их в вектор или положить свои лямбды в «контейнер», который будет собирать тип каждого элемента, кроме лямбда сам объект - std::tuple:

auto t = std::make_tuple([](){ std::cout<<"First lambda" << std::endl; }, 
         [](){ std::cout<<"Second lambda"<< std::endl; }, 
         [](){ std::cout<<"Third lambda" << std::endl; }); 

и получить соответствующий лямбда во время компиляции:

std::get<0>(t)(); // the value in get must be known at compile time! 
        // otherwise compiler won't be able to establish type 
        // of lambda and the whole point of using tuple is lost 

[live demo]