4

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

私はそれを機能させるのに問題があります.boost::functionを誤用していると思います.普通の関数ポインタと混同しています.

マップでは、特定の顧客にインスタンスを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;
}

UPDATEブースト::関数ではなく、マップで関数参照を使用することで機能しました

4

1 に答える 1

3

メンバー関数がstatic. 代わりに、特定のオブジェクト インスタンスでBoost バインドを使用する必要があります。

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

(非静的) メンバー関数ポインターが通常の関数ポインター (または静的メンバー関数ポインター) と同じではない理由は、メンバー関数には非表示の「zeroeth」引数、つまりthisメンバー関数内のポインターがあるためです。

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

boost::function<bool()>

これは、 a を返し、bool引数を取らないすべてのタイプの関数を処理します。


std::functionコンパイラが十分に新しい場合は、とを使用するように変更することもできますstd::bind


メンバー関数ポインターで表示するように編集した後:次のように、関数ポインターも正しく呼び出す必要があります。

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