Как определить вектор функций, который принимает различные типы параметров в C ++? - PullRequest
0 голосов
/ 05 февраля 2020

Я ставлю перед собой задачу и пишу программу на C ++ без использования классов и механизмов, связанных с классами. Дополнительные условия: я могу использовать все, начиная от stl, и иметь полную безопасность типов, то есть не иметь необработанных указателей или приведение типов к одному. Сейчас я нахожусь в ситуации, когда я не уверен, как поступить с наложенными на себя ограничениями.

Проблема: я хочу создать std :: vector функций, но каждая из этих функций может взять другой тип данных и работать только с этим типом. Пример:

struct DataAndFunction {
    AnyDataType data;
    std::function<void(AnyDataType&)> functionOperatingWithData;
};
...
std::vector<DataAndFunction> listOfFunctions;
...
for(auto& dataAndFunc : listOfFunctions) {
    dataAndFunc.functionOperatingWithData(dataAndFunc.data);
}

тогда будет другой тип AnyDataType и сопутствующие функции.

Я знаю, что это можно решить двумя способами:

  1. с классами, использующими полиморфизм, где

    std::vector< DataAndFunction > listOfFunctions;

просто примет базовый класс в качестве параметра шаблона и будет иметь виртуальный метод, это может быть реализовано дочерними классами, каждый из которых имеет свои собственные частные элементы данных, но суть моей задачи состоит в том, чтобы не использовать этот шаблон.

Я мог бы передать void* в качестве сигнатуры данных и функции, и внутри каждой функции я бы приводил данные к соответствующему типу, но я хочу использовать безопасность типов и только умные указатели

I можно также сделать DataAndFunction struct generi c, добавив параметр шаблона, но как мне сделать вектор, который можно заполнить не только, например, DataAndFunction<int>, но любым параметром шаблона?

А как бы решить эту проблему в более функциональном стиле? Как будет выглядеть функциональное решение в C ++, которое будет работать со списком функций, каждая из которых принимает аргумент другого типа? Конечно, без использования наследования.

Или я просто спрашиваю, как эмулировать виртуальную таблицу?

Ответы [ 2 ]

4 голосов
/ 05 февраля 2020

Кажется, вам нужно только std::function<void()>:

DataAndFunction<int> dint;
DataAndFunction<char> dchar;
std::vector<std::function<void()>> funcs{
    [&](){ dint.f(dint.data); },
    [&](){ dchar.f(dchar.data); },
    [](){ std::cout << "Hello world\n"; }
};

for (auto& f : funcs) {
    f();
}
1 голос
/ 05 февраля 2020

Как вы знаете, C ++ - это строго типизированный язык. Это означает, что вы не можете иметь переменную generic c, как это делают другие языки, например Python.

В C решение состоит в том, чтобы использовать точку на void (void*), но трудно управление и подверженность ошибкам.

C ++ 17 поставляется с 2 элегантными решениями, которые вы можете использовать:

std::any и std::variant.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...