Member 14549814 Ответов: 2

Как создать вектор функций с различными типами аргументов/возвращаемых значений?


Мне нужен вектор функций, который выглядел бы примерно так: vector<function<auto(auto)> v;но, очевидно, это не сработало...

что-то вроде этого:
#include<bits stdc++.h="">
using namespace std;
int f1(int n){
return n*2+2;
}

string f2(string n){
return n+'!';
}
int main(){
vector<function<auto(auto)>>v;v.clear();//not working

v.push_back(f1);v.push_back(f2);

cout<<v[0](5)<<endl<<v[1]("thanks");

return 0;
}


Что я уже пробовал:

если я сделаю что-то подобное, например:
вектор&ЛТ;&амп; ЛТ;инт(инт)&ГТ;&ГТ;В1; вектор&ЛТ;&амп; ЛТ;строка(string)&ГТ;&ГТ;В2;
и тогда push_back каждой функции, где она принадлежит, все в порядке...
но мне нужен один вектор для всех них ... если это возможно

Richard MacCutchan

А что за проблему вы пытаетесь решить?

Member 14549814

никто не уверен ... но это помогло бы мне в целом

Richard MacCutchan

Помочь тебе сделать что? Проблема здесь в том, что если мы не знаем, чего вы пытаетесь достичь, то трудно делать предложения.

2 Ответов

Рейтинг:
2

Stefan_Lang

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

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

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


Rick York

Я полностью с вами согласен. После всех забросов и тому подобного будет просто бардак.

Member 14549814

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

Stefan_Lang

Технически таблица виртуальных функций виртуальных классов делает нечто очень похожее: фактически это список указателей функций, содержащий указатель для каждой виртуальной функции-члена. Однако он основан на определении класса, которое предоставляет полный список сигнатур функций во время компиляции. Более того, VFT используется только производными классами и вызывается их оригинальным именем и сигнатурой. Код совсем не похож на доступ к вектору указателей функций - и это хорошо!

Рейтинг:
1

Rick York

Вот один из способов, которым это можно сделать.

typedef UINT( WINAPI * ThreadFunc )( PVOID );

typedef struct
{
    ThreadFunc  function;
    PVOID       argument;
} OneFunction;

int main()
{
    std::vector< OneFunction > functions;

    OneFunction f;

    // set the members of f here

    functions.push_back( f );

    (* functions[0].function )( functions[0].argument );  // call one
}
Вы также можете определить различные типы функций. ThreadFunc-это всего лишь один тип. Если вам нужно, вы можете разыгрывать между различными типами по мере необходимости, чтобы они не все должны были возвращать UINT. Они могут возвращать любой тип, который вы хотите, и принимать любые аргументы, которые вы хотите. Просто определите различные типы, чтобы вы могли бросать между ними по мере необходимости.


Member 14549814

Извините но я получаю несколько ошибок:
typedef 'ax' инициализируется (вместо этого используйте decltype)
"WINAPI" не был объявлен в этой области
'ThreadFunc' не был объявлен в этой области
'ThreadFunc' не называет тип
"PVOID" не называет тип|

Rick York

Отрегулируйте его, чтобы использовать типы, которые вы хотите/имеете/нуждаетесь. PVOID-это указатель на void.

Member 14549814

я не привык к таким вещам...впрочем...в любом случае спасибо

Rick York

Если вы не привыкли к такого рода вещам, то вы даже не должны думать о том, чтобы идти по этому пути, потому что это то, что требуется.

Stefan_Lang

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

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