Question

J'implémente un lecteur de paramètres générique. L'idée est que j'ai une application quels paramètres peuvent être booléens, entiers et chaînes. Ensuite, j'ai une classe de configuration où les Getters pour ces paramètres sont implémentés, la classe de configuration prend un client dans le constructeur, afin qu'il sache qu'il lira les paramètres de ce client.

J'ai du mal à faire fonctionner ce travail, je pense que j'utilise une mauvaise utilisation Boost :: Fonction la confusion avec le pointeur de fonction ordinaire.

Dans les cartes, j'aimerais avoir des références pendant que le boost::function ne doit être apporté qu'à l'heure de lecture de configuration depuis que j'ai alloué un Config Instance pour le client donné.

Le problème est que je ne peux pas utiliser de pointeurs de fonction sans type de type et cela complique le travail de modèle, une solution plus sage?

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

Mise à jour, il a fonctionné en utilisant des références de fonction dans des cartes plutôt que sur boost :: fonction

Était-ce utile?

La solution

Vous ne pouvez pas utiliser les pointeurs de fonction des membres comme pointeurs de fonction normaux, à moins que les fonctions des membres ne soient static. Vous devriez plutôt utiliser Boost Bind avec une instance d'objet spécifique:

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

La raison pour laquelle les pointeurs de fonction des membres (non statiques) ne sont pas les mêmes que les pointeurs de fonction normaux (ou les pointeurs de fonction des membres statiques) est que les fonctions des membres ont un argument "Zeroeth" caché, c'est-à-dire l'argument this pointeur à l'intérieur de la fonction membre.

De plus, votre déclaration de la boost::function Les objets ne doivent être que par exemple

boost::function<bool()>

Qui gérera tous les types de fonctions renvoyant un bool et ne prenant aucun argument.


Si votre compilateur est assez nouveau, vous voudrez peut-être également changer pour utiliser std::function et std::bind.


Après votre modification à montrer avec des pointeurs de fonction des membres: vous devez également appeler les pointeurs de fonction correctement, comme

(config.*configIter->second)();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top