سؤال

أنا أقوم بتنفيذ قارئ إعداد عام. الفكرة هي أن لديّ تطبيقًا يمكن أن تكون الإعدادات المنطقية والأعداد الصحيحة والسلاسل. بعد ذلك ، لدي فئة تكوين حيث يتم تنفيذ getters لمثل هذه الإعدادات ، يأخذ فئة التكوين عميلًا في المُنشئ ، بحيث يعرف أنه سيقرأ إعدادات لهذا العميل بالذات.

أواجه مشكلات في وجود هذا العمل ، أعتقد أنني أسيء استخدام تعزيز :: وظيفة تربكها مع مؤشر وظيفة عادي.

في الخرائط ، أود أن أحصل على مراجع أثناء 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;
}

تحديث أنه يعمل باستخدام مراجع الوظائف في الخرائط بدلاً من التعزيز :: وظيفة

هل كانت مفيدة؟

المحلول

لا يمكنك استخدام مؤشرات وظيفة الأعضاء كمؤشرات وظيفية طبيعية ، ما لم تكن وظائف الأعضاء static. يجب عليك الاستخدام بدلاً من ذلك تعزيز الربط مع مثيل كائن معين:

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

إن السبب في أن مؤشرات وظيفة الأعضاء (غير الستنية) ليست هي نفس مؤشرات الوظائف العادية (أو مؤشرات وظيفة الأعضاء الثابتة) هو أن وظائف الأعضاء لها حجة "صفر" مخفية ، وهي هي this مؤشر داخل وظيفة العضو.

أيضا ، إعلانك عن boost::function يجب أن تكون الكائنات فقط على سبيل المثال

boost::function<bool()>

التي ستتعامل مع جميع أنواع الوظائف التي تعود bool وعدم أخذ الحجج.


إذا كان المترجم الخاص بك جديدًا بما يكفي ، فقد ترغب أيضًا في التغيير لاستخدامه std::function و std::bind.


بعد التحرير الخاص بك لتظهر مع مؤشرات وظيفة الأعضاء: عليك أن تسمي مؤشرات الوظيفة بشكل صحيح أيضًا ، مثل

(config.*configIter->second)();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top