Pregunta

For this project, I cannot use C++11, or add any additional dependencies (e.g. Boost).

What I'm trying to achieve is this:

typedef void (*processorFunction)(int numItems, std::string* items);

class Files
{
public:
    Files() : m_KVSeparator('='), m_ListSeparator(',') {}
    ~Files() {}

    void ReadDataFile(std::string filename, std::map<std::string, processorFunction> processorFunctions);

    char m_KVSeparator;
    char m_ListSeparator;
};

void Files::ReadDataFile(std::string filename, std::map<std::string, processorFunction> processorFunctions)
{
    // The file parsing and choosing of the function omitted for brevity:
    processorFunction processor = ...;
    int numItems = ...;
    std::string* items = ...;

    processor(numItems, items);
}

// Example parser:
void time_limit_parser(int& timeLimit, int numItems, std::string* items)
{
    timeLimit = atoi(items[0].c_str());
}

int main()
{
    // Omitted getting the global file manager pointer
    Files* files = ...;
    std::map<std::string, processorFunction> configProcessorFunctions;
    int timeLimit;
    // ****** WHAT GOES HERE? ******
    files->ReadDataFile("config.dat", configProcessorFunctions);
}

My question is what do I put on the ****** WHAT GOES HERE? ****** line? I would use std::bind to partially apply it (a la time_limit_parser(timeLimit)), but I can't use C++11 for this project.

¿Fue útil?

Solución

You wouldn't be able to do what you wanted even with bind because bind doesn't return function pointers. Instead, you'd have to use the std::function template to wrap them.

As it turns out, there's nothing preventing you from doing exactly that yourself.

struct BaseProcessor
{
    virtual void operator()(int numItems, std::string* items) = 0;
};

struct TimeLimitParser : public BaseProcessor
{
    int& timeLimit;

    TimeLimitParser(int& limit)
        : timeLimit(limit)
    {}

    virtual void operator()(int numItems, std::string* items)
    {
        time_limit_parser(timeLimit, numItems, items);
    }
};

int main()
{
    // Omitted getting the global file manager pointer
    Files* files = ...;
    std::map<std::string, processorFunction*> configProcessorFunctions;
    int timeLimit;
    TimeLimitParser parser(timeLimit);
    configProcessorFunctions["foo"] = &parser;
    files->ReadDataFile("config.dat", configProcessorFunctions);
}

Obviously you need to change the definition of processFunction to match a pointer/reference to BaseProcessor, and it's clearly not quite as pretty as using bind or lambdas, but if you can't upgrade or get boost that's about as good at it'll get without some serious wizardry.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top