Is there an option to create a vector that contains functions with different return types?

162 Views Asked by At

I have the following vectors

std::vector<std::pair<std::string, std::function<std::string(const PlayerFRDb&)>>> stringExtractors = {
    {" TEAM ", extractTeam},
    {" NAME ", extractName},
    {" TYPE ", extractProperty4},
};

std::vector<std::pair<std::string, std::function<int(const PlayerFRDb&)>>> intExtractors = {
    {" WS ", extractProperty0},
    {" LS ", extractProperty1},
    {" W ", extractProperty2},
    {" L ", extractProperty3},
};

std::vector<std::pair<std::string, std::function<char(const PlayerFRDb&)>>> charExtractors = {
    {" WAY ", extractProperty5},
};

std::vector<std::pair<std::string, std::function<double(const PlayerFRDb&)>>> doubleExtractors = {
    {" LINE ", extractProperty6},
};

To make it easier to work with these functions, I want to lump them into one vector, but the problem is that they return different types.

I tried using std::variant, but I can't initialize the vector, because the compiler prints out: "no instance of constructor matches the argument list argument types are ({...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}) "

using FuncVariant = std::variant<
    std::function<std::string(const PlayerFRDb&)>,
    std::function<int(const PlayerFRDb&)>,
    std::function<double(const PlayerFRDb&)>
>;

std::vector<std::pair<std::string, FuncVariant>> extractors = {
    {" TEAM ", extractTeam},
    {" NAME ", extractName},
    {" TYPE ", extractProperty4},
    {" WS ", extractProperty0},
    {" LS ", extractProperty1},
    {" W ", extractProperty2},
    {" L ", extractProperty3},
    {" LINE ", extractProperty6},
};

Is there an option to create a vector that contains functions with different return types?

2

There are 2 best solutions below

0
Ahmed AEK On BEST ANSWER

to help the compiler deduce the template arguments you can wrap all functions with std::function{}.

#include <variant>
#include <functional>
#include <string>

int foo(void) {return 0;}
char bar(void) {return '0';}

using FuncVariant = std::variant<std::function<int()>,std::function<char()>>;
int main()
{
    std::vector<std::pair<std::string, FuncVariant>> vec{
        {"TEAM", std::function{bar}},
        {"W", std::function{foo}}
    };
    return 0;
}
0
Caleth On

Rather than having the variant over the function type, you can have the function type return a variant.

using FuncVariant = std::function<std::variant<std::string, int, double>(const PlayerFRDb&)>;

std::vector<std::pair<std::string, FuncVariant>> extractors = {
    {" TEAM ", extractTeam},
    {" NAME ", extractName},
    {" TYPE ", extractProperty4},
    {" WS ", extractProperty0},
    {" LS ", extractProperty1},
    {" W ", extractProperty2},
    {" L ", extractProperty3},
    {" LINE ", extractProperty6},
};