diff --git a/eo/src/eoAlgoFoundryEA.h b/eo/src/eoAlgoFoundryEA.h index 561dd6399..4f07c2c55 100644 --- a/eo/src/eoAlgoFoundryEA.h +++ b/eo/src/eoAlgoFoundryEA.h @@ -39,15 +39,19 @@ * foundry.selectors.add< eoStochTournamentSelect >( 0.5 ); * @endcode * + * @warning If the constructor takes a reference YOU SHOULD ABSOLUTELY wrap it + * in a `std::ref`, or it will silently be passed as a copy, + * which would effectively disable any link between operators. + * * In a second step, the operators to be used should be selected * by indicating their index, just like the foundry was a array of five elements: * @code * foundry = {0, 1, 2, 0, 3}; - * // ^ continue - * // ^ crossover - * // ^ mutation - * // ^ selection - * // ^ replacement + * // ^ ^ ^ ^ ^ replacement + * // | | | + selection + * // | | + mutation + * // | + crossover + * // + continue * @endcode * * @note: by default, the firsts of the five operators are selected. diff --git a/eo/src/eoForge.h b/eo/src/eoForge.h index 91731ab03..f28cd8cda 100644 --- a/eo/src/eoForge.h +++ b/eo/src/eoForge.h @@ -83,6 +83,11 @@ class eoForgeInterface * * This allows for creating containers of pre-parametrized operators (@see eoForgeVector). * + * @warning When passing a reference (as it is often the case within ParadisEO), + * it is MANDATORY to wrap it in `std::ref`, or else it will default to use copy. + * This is is a source of bug which your compiler will to detect and that would + * disable any link between operators. + * * @code eoForgeOperator,eoRankMuSelect> forge(mu); // ^ desired ^ to-be-instanciated ^ operator's @@ -101,8 +106,10 @@ template class eoForgeOperator : public eoForgeInterface { public: - eoForgeOperator(Args&&... args) : - _args(std::forward(args)...), + // Use an additional template to avoid redundant copies of decayed Args variadic. + template + eoForgeOperator(Args2... args) : + _args(std::forward(args)...), _instanciated(nullptr) { } @@ -131,7 +138,7 @@ class eoForgeOperator : public eoForgeInterface } protected: - std::tuple _args; + std::tuple _args; private: /** Metaprogramming machinery which deals with arguments lists @{ */ @@ -182,6 +189,11 @@ class eoForgeOperator : public eoForgeInterface * @note You can actually store several instances of the same class, * with different parametrization (or not). * + * @warning When passing a reference (as it is often the case within ParadisEO), + * it is MANDATORY to wrap it in `std::ref`, or else it will default to use copy. + * This is is a source of bug which your compiler will to detect and that would + * disable any link between operators. + * * @warning You may want to enable instanciation cache to grab some performances. * The default is set to disable the cache, because its use with operators * which hold a state will lead to unwanted behaviour. @@ -225,11 +237,20 @@ class eoForgeVector : public std::vector*> { } /** Add an operator to the list. + * + * @warning When passing a reference (as it is often the case within ParadisEO), + * it is MANDATORY to wrap it in `std::ref`, or else it will default to use copy. + * This is is a source of bug which your compiler will to detect and that would + * disable any link between operators. + * */ template - void add(Args&&... args) + void add(Args... args) { - auto pfo = new eoForgeOperator(std::forward(args)...); + // We decay all args to ensure storing everything by value within the forge. + // The references should thus be wrapped in a std::ref. + auto pfo = new eoForgeOperator...>( + std::forward(args)...); this->push_back(pfo); } @@ -243,15 +264,21 @@ class eoForgeVector : public std::vector*> } /** Change the set up arguments to the constructor. + * + * @warning When passing a reference (as it is often the case within ParadisEO), + * it is MANDATORY to wrap it in `std::ref`, or else it will default to use copy. + * This is is a source of bug which your compiler will to detect and that would + * disable any link between operators. * * @warning The operator at `index` should have been added with eoForgeVector::add already.. */ template - void setup(size_t index, Args&&... args) + void setup(size_t index, Args... args) { assert(index < this->size()); delete this->at(index); // Silent on nullptr. - auto pfo = new eoForgeOperator(std::forward(args)...); + auto pfo = new eoForgeOperator...>( + std::forward(args)...); this->at(index) = pfo; }