4

我正在实现一个通用设置阅读器。这个想法是我有一个应用程序,它的设置可以是布尔值、整数和字符串。然后我有一个 Config 类,其中实现了此类设置的 getter,config 类在构造函数中获取一个客户,以便它知道它将读取该客户的设置。

我在工作时遇到了麻烦,我认为我在滥用 boost::function 将它与普通函数指针混淆。

在地图中,我希望有引用,而boost::function应该只在配置读取时绑定,因为我已经Config为给定的客户分配了一个实例。

问题是我不能使用没有 typedef 的函数指针,这会使模板工作复杂化,有什么更明智的解决方案吗?

#include "Config.h"

class ConfigReader
{

    ConfigReader();

    template<class R>
    R readConfig(std::string customer, std::string settingName);

private:

        typedef bool (Config::* BoolConfigFunctor) () const;
    std::map<std::string, BoolConfigFunctor> boolConfigMap;

        typedef int(Config::* IntConfigFunctor) () const;
    std::map<std::string, IntConfigFunctor> integerConfigMap;

        typedef std::string (Config::* StrConfigFunctor) () const;
    std::map<std::string, StrConfigFunctor> stringConfigMap;

    template<class R>
    std::map<std::string, R (Config::* ) () >  getConfigMap();
}

ConfigReader()
{
    // INIT all settings you want to be readable in the functor maps
    boolConfigMap["USE_NEW_VERSION"]    = &Config::useNewVersion;
    boolConfigMap["MAINTENANCE_MODE"]   = &Config::isMaintenance;
    integerConfigMap["TIMEOUT"]         = &Config::getTimeout;
    stringConfigMap["USERNAME"]         = &Config::getUserName;
            ...
}

template<class R>
R readConfig(std::string customer, std::string settingName)
{
    R returnValue;

    typedef typename std::map<AMD_STD::string,  R (Config::* ) () > ConfigMap_t;
    typedef typename ConfigMap_t::const_iterator ConfigMapIter_t;

    ConfigMap_t configMap = getConfigMap<R>();
    ConfigMapIter_t configIter = configMap.find(settingName);

    if (configIter != configMap.end())
    {
        Config config(customer); // Real instance of Config against which we want to call the function

        boost::function<R ()> configFunction;
        configFunction =
                boost::bind(
                        configIter->second,
                        config);

        returnValue= configFunction();
    }

    return returnValue;
}

template<>
std::map<std::string, bool (Config::* ) ()>  ConfigReader::getConfigMap()
{
    return boolConfigMap;
}

template<>
std::map<std::string, int (Config::* ) ()>  ConfigReader::getConfigMap()
{
    return integerConfigMap;
}

template<>
std::map<std::string, string (Config::* ) ()>  ConfigReader::getConfigMap()
{
    return stringConfigMap;
}

更新它确实通过在地图中使用函数引用而不是 boost::function 来工作

4

1 回答 1

3

您不能将成员函数指针用作普通函数指针,除非成员函数是static. 您应该将Boost 绑定与特定对象实例一起使用:

boolConfigMap["USE_NEW_VERSION"] = boost::bind(&Config::useNewVersion, someInstanceOfConfig);

(非静态)成员函数指针与普通函数指针(或静态成员函数指针)不同的原因是成员函数有一个隐藏的“zeroeth”参数,即this成员函数内部的指针。

此外,您对boost::function对象的声明应该只是例如

boost::function<bool()>

这将处理所有类型的函数返回 abool并且不带参数。


如果您的编译器足够新,您可能还想更改为使用std::functionand std::bind


编辑后显示成员函数指针:您还必须正确调用函数指针,例如

(config.*configIter->second)();
于 2013-11-07T11:58:57.483 回答