Partage
  • Partager sur Facebook
  • Partager sur Twitter

std::make_pair recalcitrant

Sujet résolu
    23 août 2018 à 2:15:50

    Bonjour,

    J'essaye d'implémenter le DP Service Locator, avec 2 services de génération de nombre aléatoire (le premier entre 0 et 10, le second entre 0 et 100).

    Ma classe serviceLocator contient un conteneur map pour retrouver les services via leur nom, mais lors de l'insertion d'un service via std::make_pair (ligne 58), le compilateur me crache son venin, et les messages d'erreur de VS me laissent perplexe.

    Le code:

    #include <iostream>
    #include <map>
    #include <chrono>
    #include <random>
    #include <memory>
    #include <cassert>
    
    class IRandomNumber
    {
    protected:
    	std::default_random_engine mEngine;
    public:
    	IRandomNumber() : mEngine{ static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()) }
    	{}
    	virtual ~IRandomNumber() {}
    	virtual unsigned get() = 0;
    };
    
    class randomNumber10 : public IRandomNumber
    {
    private:
    public:
    	randomNumber10(): IRandomNumber::IRandomNumber()
    	{}
    	unsigned get()
    	{
    		std::uniform_int_distribution<int> distribution{ 0, 10 };
    		return distribution(IRandomNumber::mEngine);
    	}
    };
    
    class randomNumber100 : public IRandomNumber
    {
    private:
    public:
    	randomNumber100() : IRandomNumber::IRandomNumber()
    	{}
    	unsigned get()
    	{
    		std::uniform_int_distribution<int> distribution{ 0, 100 };
    		return distribution(IRandomNumber::mEngine);
    	}
    };
    
    class serviceLocator
    {
    private:
    	static std::map<std::string, std::unique_ptr<IRandomNumber>> mServices;
    public:
    	static void registerService(std::unique_ptr<IRandomNumber> service, const std::string& name);
    	static IRandomNumber* getService(std::string name);
    };
    
    std::map<std::string, std::unique_ptr<IRandomNumber>> serviceLocator::mServices{};
    
    void serviceLocator::registerService(std::unique_ptr<IRandomNumber> service, const std::string& name)
    {
    	mServices.insert(std::make_pair(std::string(name), service));
    }
    
    IRandomNumber* serviceLocator::serviceLocator::getService(std::string name)
    {
    	auto found = mServices.find(name);
    	assert(found != mServices.end());
    	return found->second.get();
    }
    
    int main()
    {
    	serviceLocator::registerService(std::move(std::make_unique<randomNumber10>()), "randomNumber10");
    	serviceLocator::registerService(std::move(std::make_unique<randomNumber100>()), "randomNumber100");
    
    	for (unsigned i = 0; i < 10; ++i)
    	{
    		std::cout << serviceLocator::getService("randomNumber10")->get() << "\t" << serviceLocator::getService("randomNumber100")->get() << std::endl;
    	}
    }
    

    Et les erreurs:

    1>c:\...\include\utility(360): error C2440: '<function-style-cast>' : impossible de convertir de 'initializer list' en '_Mypair'
    1>c:\...\include\utility(360): note: Aucun constructeur n'a pu prendre le type de source, ou la résolution de la surcharge du constructeur était ambiguë
    1>c:\...\main.cpp(58): note: voir la référence à l'instanciation de la fonction modèle 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char>>,std::unique_ptr<IRandomNumber,std::default_delete<_Ty>>> std::make_pair<std::string,std::unique_ptr<_Ty,std::default_delete<_Ty>>&>(_Ty1 &&,_Ty2)' en cours de compilation
    1>        with
    1>        [
    1>            _Ty=IRandomNumber,
    1>            _Ty1=std::string,
    1>            _Ty2=std::unique_ptr<IRandomNumber,std::default_delete<IRandomNumber>> &
    1>        ]
    • Partager sur Facebook
    • Partager sur Twitter
      23 août 2018 à 2:36:44

      En utilisant make_pair, tu fais une copie des paramètres. Or, service est un unique_ptr et ne peut être copié. Ce n'est pas l'insertion qui échoue, mais la création de la paire.

      • Dans std::make_pair(std::string(name), service), std::string est inutile.
      • Utilise emplace: mServices.emplace(name, std::move(service))
      • Partager sur Facebook
      • Partager sur Twitter
        23 août 2018 à 2:55:41

        Merci.

        Autre curiosité avec les distributions, modifient t'elles le generateur ?
        Je n'ai pas pu qualifier la fonction get() en const (ce qui logiquement devrais être le cas).

        • Partager sur Facebook
        • Partager sur Twitter
          23 août 2018 à 16:49:26

          Bien sûr qu'elle modifie le générateur. Quand on génère un nombre aléatoire, on modifie l'état interne du générateur, sinon on piocherait toujours le même nombre.

          • Partager sur Facebook
          • Partager sur Twitter
            1 septembre 2018 à 12:46:27

            Après quelques expérimentations, conceptuellement parlant, est-ce que ceci est correcte (const_cast) ?

            class nonCopyable
            {
            public:
                nonCopyable() = default;
                nonCopyable(const nonCopyable&) = delete;
                nonCopyable& operator=(const nonCopyable&) = delete;
                virtual ~nonCopyable()
                {}
            };
            
            class IRandomNumber
            {
            protected:
                std::default_random_engine mEngine;
            public:
                IRandomNumber():
                    mEngine{ static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()) }
                {}
            
                virtual ~IRandomNumber()
                {}
            
                virtual unsigned get() const = 0;
            };
            
            class randomNumber10 : public IRandomNumber,
                                   public nonCopyable
            {
            public:
                unsigned get() const override final
                {
                    std::uniform_int_distribution distribution{ 0, 10 };
                    return distribution(const_cast<std::default_random_engine&>(IRandomNumber::mEngine));
                }
            };



            • Partager sur Facebook
            • Partager sur Twitter
              1 septembre 2018 à 14:14:14

              Je ne trouve pas. Si j'utilise cette classe dans une fonction, je m'attends à avoir toujours le même comportement. Or comme get() retourne un nombre différent à chaque fois ce n'est pas possible. Je trouve aussi que le nom est très mal choisi, next() ou nextNumber() serait beaucoup plus parlant et sans ambiguïté.

              • C'est IRandomNumber qui devrait hériter de nonCopyable, pas les classes filles.
              • Est-ce vraiment nécessaire de passer par des fonctions virtuelles ? Actuellement seuls les paramètres de uniform_int_distribution changent.
              • Si une interface IRandom est utile, alors mEngine ne devrait pas s'y trouver: un générateur aléatoire depuis une séquence pré-établie n'en a pas besoin par exemple. Même chose si j'en veux un autre que celui par défaut.
              • lié la classe au temps courant empêche toute tentative de faire des tests.
              • Partager sur Facebook
              • Partager sur Twitter
                1 septembre 2018 à 14:25:12

                Salut,

                A vrai dire, je vois trois problèmes conceptuels dans ta solution:

                • l'utilisation de const_cast est souvent le signe d'une problème plus profond
                • l'accessibilité protégée ne devrait contenir que des fonctions (tout comme l'accessibilité publique)
                • tu n'as aucune raison d'avoir autant de générateurs aléatoires que tu auras d'instances dérivées de IRandomNumber: un générateur pour l'ensemble sera amplement suffisant ;)

                On pourrait résoudre ces trois problèmes "simplement" rendant le générateur indépendant de toute instance de IRandomNumber et, pour faire bonne mesure, en le rendant accessible au travers d'une fonction qui soit --elle aussi -- indépendante de toute instance de IRandomNumber.

                Du coup, nous pourrions avoir un code proche de

                class nonCopyable
                {
                public:
                    nonCopyable() = default;
                    nonCopyable(const nonCopyable&) = delete;
                    nonCopyable& operator=(const nonCopyable&) = delete;
                    virtual ~nonCopyable() = default;
                };
                 
                class IRandomNumber
                {
                    /* par facilité */
                    using engine_type = std::default_random_engine;
                public:
                 
                    virtual ~IRandomNumber()= default;
                 
                    virtual unsigned get() const = 0;
                protected:
                    static engine_type& engine(){
                        static engine_type eng{static_cast<unsigned>(
                            std::chrono::high_resolution_clock::now().time_since_epoch().count()) };
                		return eng;
                	}
                };
                 
                class randomNumber10 : public IRandomNumber,
                                       public nonCopyable
                {
                public:
                    unsigned get() const override final
                    {
                        std::uniform_int_distribution<unsigned> distribution{ 0, 10 };
                        return distribution(engine());
                    }
                };

                qui produira le résultat souhaité ;)

                NOTA: Tu pourrais même éviter la virtualité de get en ajoutant les valeurs minimales et maximale de la distribution directement dans IRandomNumber (qui pourrait carrément devenir une classe template, du coup), ce qui pourrait donner quelque chose comme

                class nonCopyable
                {
                protected:
                    nonCopyable() = default;
                    nonCopyable(const nonCopyable&) = delete;
                    nonCopyable& operator=(const nonCopyable&) = delete;
                    ~nonCopyable() = default;
                };
                template <unsigned MIN, unsigned MAX>
                class IRandomNumber : private nonCopyable
                {
                	using engine_type = std::default_random_engine;
                public:
                    unsigned get() const{
                        
                        std::uniform_int_distribution<unsigned> distribution{ MIN, MAX };
                        return distribution(engine());
                	}
                protected:
                    static engine_type& engine(){
                		static engine_type eng{static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count()) };
                		return eng;
                	}
                };
                /* un générateur aléatoire spécifique peut alors n'être qu'un 
                 * alias de type
                 */
                using randomNumber10 = IRandomNumber;

                (attention, j'en ai profité pour "corriger" ta classe nonCopyable, et pour l'utiliser en héritage privé, comme il se doit pour ce genre de classe ;) )

                -
                Edité par koala01 1 septembre 2018 à 14:40:41

                • Partager sur Facebook
                • Partager sur Twitter
                Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                  6 septembre 2018 à 22:49:40

                  Ne vous focalisez pas trop sur les classes, le but était de mettre en œuvre le design pattern Service Locator.
                  Ce qui me tracasse est le fait que la fonction membre get() n'est pas constante.

                  Merci Koala, ta solution est élégante.
                  Finalement c'est la classe ServiceLocator que j'ai mis en Template.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    7 septembre 2018 à 3:27:33

                    Ah, ben, j'ai peut être que chose qui pourrait t'intéresser...

                    Je te le donne en vrac, si tu veux des explications, tu n'as qu'à demander :D

                    struct UniqueTag{};
                    struct StackTag{};
                    struct MultipleTag{};
                    struct ChangeTag{};
                    struct NoChangeTag{};
                    struct CopyTag{};
                    struct NoCopyTag{};
                    
                    namespace Details{
                    using index_t = std::type_index;
                    inline index_t const & voidIndex(){
                    	static const index_t v{typeid(void)};
                    	return v;
                    }
                    struct IndexCheckPolicy{
                    	template <typename Derived>
                    	static void check(index_t const & check){
                    		index_t id{typeid(Derived)};
                    		assert(id == check && "Bad type requested");
                    	}
                    };
                    template <typename Base>
                    class PseudoBase{
                    public:
                    	PseudoBase() = default;
                    	PseudoBase(PseudoBase const &)= delete;
                    	PseudoBase & operator = (PseudoBase const &) = delete;
                    	virtual ~PseudoBase() = default;
                    };
                    template <typename Derived, typename Base>
                    class PseudoPoly : public PseudoBase<Base>{
                    	
                    public:
                    
                    	
                    	template <typename  ... Args>
                    	PseudoPoly(Args ... args):
                    		value{args ...}{
                    			
                    	}
                    	Derived value;
                    };
                    
                    template <typename Base, bool>
                    struct PolymorphicTrait{
                    	using pointer_t = std::unique_ptr<Base>;
                    	static constexpr bool baseable{true};
                    };
                    template <typename Base>
                    struct PolymorphicTrait<Base, false>{
                    	using pointer_t = std::unique_ptr<PseudoBase<Base>>;
                    	static constexpr bool baseable{false};
                    };
                    template <typename Base, bool>
                    struct PointerCreator{
                    	using trait_t = PolymorphicTrait<Base, true>;
                    	using pointer_t = typename trait_t::pointer_t;
                    	
                    	template <typename Derived, typename  ... Args>
                    	static pointer_t create(Args ... args){
                    		static_assert(std::is_base_of<Base, Derived>::value,
                    		"Base type should be parent base of Derived");
                    		return std::make_unique<Derived>(args...);
                    	}
                    };
                    template <typename Base>
                    struct PointerCreator<Base,false>{
                    	using trait_t = PolymorphicTrait<Base, false>;
                    	using pointer_t = typename trait_t::pointer_t;
                    	template <typename Derived, typename  ... Args>
                    	static pointer_t create(Args ... args){
                    		static_assert(!std::is_base_of<Base, Derived>::value,
                    		"Base type should be parent base of Derived");
                    		return std::make_unique<PseudoPoly<Derived, Base>>(args...);
                    	}
                    };
                    template <typename Base, bool>
                    struct ConvertPolicy{
                    	using trait_t = PolymorphicTrait<Base, true>;
                    	using pointer_t = typename trait_t::pointer_t;
                    	using checker_t = IndexCheckPolicy;
                    	template <typename Derived>
                    	static Derived& convert(pointer_t & pointer, index_t const & id){
                    		checker_t::template check<Derived>(id);
                    		return static_cast<Derived &>(*(pointer.get()));
                    	}
                    };
                    
                    template <typename Base>
                    struct ConvertPolicy<Base, false>{
                    	using trait_t = PolymorphicTrait<Base, false>;
                    	using pointer_t = typename trait_t::pointer_t;
                    	using checker_t = IndexCheckPolicy;
                    	template <typename Derived>
                    	static Derived& convert(pointer_t & pointer, index_t const & id){
                    		checker_t::template check<Derived>(id);
                    		return static_cast<PseudoPoly<Derived, Base> *>(pointer.get())->value;
                    	}
                    };
                    template <typename Base>
                    struct BaseConverterPolicy{
                    	using trait_t = PolymorphicTrait<Base, std::is_polymorphic<Base>::value>;
                    	using pointer_t = typename trait_t::pointer_t;
                    	static Base & convert(pointer_t & pointer){
                    		static_assert(std::is_polymorphic<Base>::value,
                    		"Only polymorphic object work here");
                    		return *(pointer.get());
                    	}
                    };
                    template <typename Base>
                    struct PointerDatasTrait{
                    	using trait_t = PolymorphicTrait<Base, std::is_polymorphic<Base>::value>;
                    	static constexpr bool baseable = trait_t::baseable;
                    	using creator_t = PointerCreator<Base, baseable>;
                    	using pointer_t = typename creator_t::pointer_t;
                    	using converter_t = ConvertPolicy<Base, baseable>;
                    };
                    template <typename Base>
                    struct PointerDatas{
                    	using trait_t = PointerDatasTrait<Base>;
                    	typename trait_t::pointer_t pointer{nullptr};
                    	index_t index{voidIndex()};
                    };
                    template <typename Base>
                    struct PointerDataCreator{
                    	using data_t = PointerDatas<Base>;
                    	using trait_t = PointerDatasTrait<Base>;
                    	using creator_t = typename trait_t::creator_t;
                    	template <typename Derived, typename ... Args>
                    	static data_t create(Args ... args){
                    		data_t result;
                    		auto temp = creator_t::template create<Derived>(args ... );
                    		result.pointer.swap(temp);
                    		result.index=(typeid(Derived));
                    		return result;
                    	}
                    };
                    template <typename Base>
                    	struct RestrictedChangePolicy{
                    	using data_t = PointerDatas<Base>;
                    	static void check(data_t const & d){
                    		assert(d.pointer == nullptr &&
                    			   d.index == voidIndex() &&
                    			   "NoChangeAllowed");
                    	}
                    };
                    template <typename Base, typename Tag>
                    struct ChangePolicy{
                    	static_assert(std::is_same<Tag, ChangeTag>::value ||
                    	              std::is_same<Tag, NoChangeTag>::value,
                    	   "Only tags ChangeTag and NoChangeTag ar allowed");
                    	 using data_t = PointerDatas<Base>;
                    	 using creator_t = PointerDataCreator<Base>;
                    	 template <typename Derived, typename ... Args >
                    	 static void change(data_t & d, Args ... args){
                    		 auto temp=creator_t::template create<Derived>(args ...);
                    		 std::swap(d.pointer, temp.pointer);
                    		 std::swap(d.index, temp.index);
                    	 }
                    }; 
                    template <typename Base>
                    struct ChangePolicy<Base, NoChangeTag>{
                    	 using data_t = PointerDatas<Base>;
                    	 template <typename Derived, typename ... Args >
                    	 static void change(data_t & d, Args ... args){
                    		 RestrictedChangePolicy<Base>::check(d);
                    		 ChangePolicy<Base, ChangeTag>::template change<Derived>(d, args ...);
                    	 }
                    	
                    };
                    template <typename Base>
                    struct Reseter{
                    	using pointer_t = PointerDatas<Base>;
                    	static void reset(pointer_t & p){
                    		p.pointer.reset();
                    		p.index= voidIndex();
                    	}
                    };
                    template <typename Base, typename Tag>
                    class UniqueHolder{
                    	using data_t      = PointerDatas<Base>;
                    	using trait_t     = PointerDatasTrait<Base>;
                    	using changer_t   = ChangePolicy<Base, Tag>;
                    	using converter_t = typename trait_t::converter_t;
                    	using poly_t     = typename trait_t::trait_t;
                    public:
                    	template <typename Derived, typename ... Args>
                    	void provides(Args ... args){
                    		changer_t::template change<Derived>(data_,args ...);
                    	}
                    	template <typename Derived>
                    	Derived & get(){
                    		return converter_t::template convert<Derived>(data_.pointer, data_.index);
                    	}
                    	template <typename =std::enable_if<poly_t::baseable>>
                    	Base & asBase(){
                    		return BaseConverterPolicy<Base>::convert(data_.pointer);
                    	}
                    	void clear(){
                    		Reseter<Base>::reset(data_);
                    	}
                    private:
                    	data_t data_;
                    };
                    template <typename Base, typename Tag>
                    class MultipleHolder{
                    	using data_t      = PointerDatas<Base>;
                    	using trait_t     = PointerDatasTrait<Base>;
                    	using changer_t   = ChangePolicy<Base, Tag>;
                    	using converter_t = typename trait_t::converter_t;
                    	using poly_t      = typename trait_t::trait_t;
                    	using map_t 	  = std::map<index_t, data_t>;
                    public :
                    	template <typename Derived, typename ... Args>
                    	void provides(Args ... args){
                    		index_t temp{typeid(Derived)};
                    		assert(datas_.find(temp)== datas_.end() &&
                    			   "item exists");
                    		changer_t::template change<Derived>(datas_[temp], args ...);
                    	}
                    	template <typename Derived>
                    	Derived & get(){
                    		index_t temp{typeid(Derived)};
                    		auto  it = datas_.find(temp);
                    		assert(it!= datas_.end() && 
                    				"item doesn't exists");	
                    		return converter_t::template convert<Derived>(it->second.pointer, it->second.index);
                    	}
                    	template <typename Derived,
                    	          typename = std::enable_if<std::is_base_of<Base, Derived>::value>>
                    	Base & asBase(){
                    		static_assert(std::is_polymorphic<Base>::value,
                    		"only accessible with polymorphic items");
                    		return get<Derived>();
                    	}
                    	void clear(){
                    		datas_.clear();
                    	}
                    private:
                    	map_t datas_;
                    };
                    template <typename Base, typename Tag>
                    class  StackBase{
                    	using stack_t = std::stack<Base>;
                    	static_assert(std::is_same<Tag, CopyTag>::value ||
                    	              std::is_same<Tag, NoCopyTag>::value,
                    	              "only CopyTag and NoCopyTag are allowed here");
                    public:
                    	template <typename ... Args>
                    	void provides(Args ... args){
                    		assert(empty() && "Stack ammorced");
                    		stack_.emplace(args ...);
                    	}
                    	void pop(){
                    		assert(!empty() && "no more item on stack");
                    		stack_.pop();
                    	}
                    	Base & top(){
                    		assert(!empty() && "no more item on stack");
                    		return stack_.top();
                    	}
                    	size_t size() const{
                    		return stack_.size();
                    	}
                    	bool empty() const{
                    		return stack_.empty();
                    	}
                    protected :
                        stack_t & stack(){
                    		return stack_;
                    	}
                    private:
                    	stack_t stack_;
                    };
                    template <typename Base, typename Tag>
                    class StackHolder : public StackBase<Base, Tag>{
                    public:
                    	void push(){
                    		auto const it = StackBase<Base, Tag>::top();
                    		StackBase<Base, Tag>::stack().push(it);
                    	}
                    };
                    template <typename Base>
                    class StackHolder<Base, NoCopyTag> : public StackBase<Base, NoCopyTag>{
                    public:
                    	template <typename ... Args>
                    	void push(Args ... args){
                    		StackBase<Base, NoCopyTag>::stack().emplace(args ...);
                    	}
                    };
                    
                    template <typename Base, typename Arity, typename Tag>
                    struct LocatorTrait{
                    	static_assert(std::is_same<Tag, ChangeTag>::value ||
                    	              std::is_same<Tag, NoChangeTag>::value,
                    	              "Only ChangeTag and NoChangeTag are allowed");
                    	using holder_t = UniqueHolder<Base,Tag>;
                    };
                    template <typename Base, typename Tag>
                    struct LocatorTrait<Base, MultipleTag, Tag>{
                    	static_assert(std::is_same<Tag, NoChangeTag>::value,
                    	              "Only NoChangeTag is allowed");
                    	using holder_t = MultipleHolder<Base,Tag>;
                    };
                    template <typename Base, typename Tag>
                    struct LocatorTrait<Base, StackTag, Tag>{
                    	static_assert(std::is_same<Tag, CopyTag>::value ||
                    	              std::is_same<Tag, NoCopyTag>::value,
                    	              "Only CopyTag and NoCopyTag are allowed");
                    	using holder_t = StackHolder<Base,Tag>;
                    };
                    template <typename Base, typename Arity,typename Tag>
                    struct LocatorBase{
                    	using trait_t=LocatorTrait<Base, Arity, Tag>;
                    	using holder_t = typename trait_t::holder_t;
                    public:
                    	template <typename Derived, typename ... Args>
                    	static void provides(Args ... args){
                    		holder().template provides<Derived>(args ...);
                    	}
                    	template <typename Derived>
                    	static Derived & get(){
                    		return holder().template get<Derived>();
                    	}
                    	template <typename = std::enable_if<std::is_polymorphic<Base>::value>>
                    	static Base & asBase(){
                    		return holder().asBase();
                    	}
                    	static void clear(){
                    		holder().clear();
                    	}
                    protected:
                        static holder_t& holder(){
                    		static holder_t h;
                    		return h;
                    	}
                    };
                    template <typename Base>
                    struct LocatorBase<Base, MultipleTag, NoChangeTag>{
                    	using trait_t=LocatorTrait<Base, MultipleTag, NoChangeTag>;
                    	using holder_t = typename trait_t::holder_t;
                    public:
                    	template <typename Derived, typename ... Args>
                    	static void provides(Args ... args){
                    		holder().template provides<Derived>(args ...);
                    	}
                    	template <typename Derived>
                    	static Derived & get(){
                    		return holder().template get<Derived>();
                    	}
                    	template <typename Derived, 
                    			  typename = std::enable_if<std::is_polymorphic<Base>::value>>
                    	static Base & asBase(){
                    		return get<Derived>();
                    	}
                    	static void clear(){
                    		holder().clear();
                    	}
                    protected:
                        static holder_t& holder(){
                    		static holder_t h;
                    		return h;
                    	}
                    };
                    template <typename Base, typename Tag>
                    class StakLocatorBase{
                    	static_assert(std::is_same<Tag, CopyTag>::value ||
                    	              std::is_same<Tag, NoCopyTag>::value,
                    	              "Only CopyTag and NoCopyTag are allowed here");
                    	using trait_t=LocatorTrait<Base, StackTag, Tag>;
                    	using holder_t = typename trait_t::holder_t;
                    public:
                    	template <typename ... Args>
                    	static void provides(Args ... args){
                    		holder().provides(args ...);
                    	}
                    	static Base & top(){
                    		return holder().top();
                    	}
                    	static void pop(){
                    		holder().pop();
                    	}
                    	static size_t count(){
                    		return holder().size();
                    	}
                    	static bool empty(){
                    		return holder().empty();
                    	}
                    protected:
                        static holder_t & holder(){
                    		static holder_t h;
                    		return h;
                    	}
                    };
                    template <typename Base, typename Tag>
                    class LocatorBase<Base, StackTag, Tag> :public StakLocatorBase<Base, Tag>{
                    public:
                    	static void push(){
                    		StakLocatorBase<Base, Tag>::holder().push();
                    	}
                    };
                    template <typename Base>
                    class LocatorBase<Base, StackTag, NoCopyTag> :public StakLocatorBase<Base, NoCopyTag>{
                    public:
                         template <typename ... Args>
                    	static void push(Args ... args){
                    		StakLocatorBase<Base, NoCopyTag>::holder().push(args...);
                    	}
                    };
                    } // namespace Details
                    
                    /**@}*/
                    /**@}*/
                    /**@}*/
                    
                    /** @ingroup Tools{
                      */
                    /** @ingroup Locator{
                     */
                    template <typename Base, typename Tag = NoChangeTag>
                    using UniqueLocator = Details::LocatorBase<Base,UniqueTag, Tag>;
                    template <typename Base>
                    using MultipleLocator = Details::LocatorBase<Base,MultipleTag, NoChangeTag>;
                    template <typename Type, typename Tag = CopyTag>
                    using StackedLocator = Details::LocatorBase<Type, StackTag,Tag>;
                    
                    template <typename Base>
                    void fillMultipleLocator(){
                    }
                    template <typename Base,typename F, typename ... Args>
                    void fillMultipleLocator(){
                        static_assert(std::is_default_constructible<F>::value,
                        "Data type should be default constructible");
                        MultipleLocator<Base>::template provides<F>();
                        fillMultipleLocator<Base,Args ...>();
                    }

                    C'est vachement long, mais  ca fait meme le café :D

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                      11 septembre 2018 à 23:29:10

                      C'est pourtant simple!!! :D

                      trois politiques de localisation "primaires":

                      • on localise un seul élément à la fois "à un instant T"
                      • on localise plusieurs éléments à la fois à "un instant T"
                      • on localise uniquement l'élément qui se trouve "en au d'une pile" "à un instant T"

                      Pour la localisation d'un seul élément à un instant T, il y a deux politiques "secondaires":

                      • on peut modifier "à tout moment" le type de l'élément localisé
                      • on ne peut pas modifier le type de l'élément localisé une fois qu'il a été défini

                      Pour la localisation du "premier élément dans une pile", encore deux politiques secondaires:

                      • l'ajout d'un élément dans la pile crée une copie de l'élément précédant
                      • l'ajout d'un élément dans la pile crée un "élément indépendant" du précédant

                      Pour la localisaton "unique" et pour la localisation "multiple", on a deux grandes catégories "d'éléments localisables" :

                      • les éléments qui interviennent dans une hiérarchie de classes classiques (sémantique d'entité, polymorphisme et héritage "inside")
                      • les éléments non polymorphes, qui n'interviennent pas dans une hiérarchie classique, mais qui représentent malgré tout des "notions communes"

                      Les différentes politiques sont déterminées à l'aide de tag:

                      • UniqueTag;
                      • MultipleTag;
                      • StackedTag;

                      pour les politiques primaires et

                      • ChangeTag;
                      • NoChangeTag;
                      • CopyTag
                      • NoCoytag;

                      pour les politiques secondaires

                      La sélection des traits se fait automatiquement, sur base de la présence (ou non) d'une fonction virtuelle.

                      Des alias de type destinés à faciliter le travail

                      une fonction libre pour faciliter le "remplissage" du localisateur multiple.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait

                      std::make_pair recalcitrant

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown