C ++ Массив различных функций - PullRequest
0 голосов
/ 02 августа 2020

Легко сделать что-то подобное в Python, но реализовать это на C ++ кажется более сложной задачей.

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

Вот что я хочу сделать.

У меня есть список значений разных типов (строка, целое число, также может быть экземпляром некоторого класса et c. ). Теперь вот первая проблема - в C ++ (в отличие от Python) все значения в векторе / массиве должны быть одного типа.

Решение, которое я вижу, заключается в том, что я могу использовать std::any вот так : vector<std::any> list.

У меня также есть массив / вектор функций (или указатели на функции) с разными типами параметров и возвращаемыми значениями - одна функция может принимать строку и целое число и возвращать символ, а другая может принимать char и вернуть int. Вот еще одна проблема: в C ++ вы можете иметь массив / вектор функций, только если они имеют одинаковые параметры и возвращаемые значения (насколько мне известно), потому что в вашем объявлении вектора вам нужно определить типы параметров и возвращаемое значение .

Другая проблема в том, что мне нужно получить информацию о параметрах и возвращаемом значении для каждой функции. Другими словами, имея эти функции, мне нужно знать, что эта функция принимает 2 строки и 1 целое число и, например, возвращает символ. В Python я могу использовать функцию inspect.signature для получения информации об аннотациях типов функции. В C ++ я не знаю, есть ли способ сделать это.

Решение, которое я вижу здесь, - это снова использовать std :: any (хотя я буду использовать другое решение, позже я объясню, почему

Решение, которое я вижу для этой проблемы, состоит в том, что я не буду извлекать эту информацию, а вместо этого пользователь класса, который принимает этот вектор функций, просто должен будет указать, какие типы параметров и какие типы параметров возвращаются. значение для каждой функции. Другими словами, решение, которое я вижу, состоит в том, что я не буду получать информацию о типах параметров программно.

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

arguments = [1, 'str', some_object] // here I prepare a list of arguments (they are of different types)
func(**arguments)

В C ++ я тоже могу распаковывать, но не, если параметры имеют разные типы.

Решение, которое я вижу здесь как следует. Все эти функции в векторе будут принимать только аргумент vector<std::any> args, который просто будет содержать все аргументы. Позже, когда я захочу вызвать функцию, я просто построю вектор со значениями std :: any и передам его в качестве аргумента. Это также решило бы предыдущую проблему невозможности сохранить вектор функций с разными параметрами.

Вы видите лучшие решения?

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

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Я считаю, что вы ищете std::apply. Вы можете использовать std::tuple вместо std::vector для хранения списка значений разных типов, если типы известны во время компиляции. Тогда std::apply(f, t) в C ++ в основном то же самое, что f(*t) в Python.

0 голосов
/ 06 августа 2020

У меня есть список значений разных типов (строка, целое число, также может быть экземпляром некоторого класса et c.).

Тип, который является объединением подтипов, называется типом суммы или помеченное объединение . В C ++ для этого есть шаблон std::variant.

Теперь вот первая проблема - в C ++ (в отличие от Python) все значения в векторе / массиве должны иметь того же типа.

Конечно, поэтому используйте с умом C ++ контейнеры . Возможно, вам понадобится std :: map или std :: vector вашего конкретного экземпляра std::variant.

У меня также есть массив / вектор функций

Вы, вероятно, захотите std::vector из std::function и код с C ++ лямбда-выражениями

Вам следует прочтите хорошую книгу по программированию на C ++

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

Вы можете почерпнуть вдохновение из SWIG и рассмотреть создание некоторого кода C ++ в вашей библиотеке. Поэтому напишите (в Python или C ++) вашу метапрограмму C ++ (генерирующую некоторый код C ++, например, ANTLR ), который генерирует код пользователя, и ваш пользователь адаптирует его инструмент автоматизации сборки для такой потребности (как пользователи GNU bison делают). См. Также этот черновой отчет и проект RefPerSys (который генерирует некоторый код C ++).

Вы также можете рассмотреть возможность внедрения Guile (или Lua) в вашем приложении.

PS. Возможно, вас заинтересуют другие языки программирования, такие как Ocaml , Go, Scheme Guile , и прочтите SICP ), Common Lisp SBCL ) или Rust .

...