質問

一般的な設定リーダーを実装しています。アイデアは、設定がブール値、整数、文字列になる可能性があるアプリケーションがあるということです。次に、そのような設定のゲッターが実装されている構成クラスがあり、構成クラスはコンストラクターに顧客を連れて行くので、その顧客の設定を読み取ることがわかります。

私はその動作をするのに問題があります、私はそれをプレーン関数ポインターと混同している::関数を誤用していると思います。

マップでは、参照がありますが boost::function 私はそこに割り当てたので、構成読み取り時間にのみバインドされなければならない Config 指定された顧客のインスタンス。

問題は、typedefsなしでは機能ポインターを使用できないということです。これにより、テンプレートの作業が複雑になります。

#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;
}

更新:: functionではなくマップで関数参照を使用して機能しました

役に立ちましたか?

解決

メンバー関数がある場合を除き、メンバー関数ポインターを通常の関数ポインターとして使用することはできません。 static. 。代わりに使用する必要があります ブーストバインド 特定のオブジェクトインスタンスで:

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

(非静的な)メンバー関数ポインターが通常の関数ポインター(または静的メンバー関数ポインター)と同じではない理由は、メンバー関数が隠された「ゼロ」引数を持っていることです。 this メンバー関数内のポインタ。

また、あなたの宣言 boost::function オブジェクトは、たとえばのみである必要があります

boost::function<bool()>

これにより、あらゆる種類の関数が返されます bool そして、議論をしません。


コンパイラが十分に新しい場合は、使用するために変更することもできます std::functionstd::bind.


編集してメンバー関数ポインターを表示する後:関数ポインターを正しく呼び出す必要があります。

(config.*configIter->second)();
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top