fix: pass everything by copy in forges
- Only way to avoid references to out-of-scope variables. - Add warnings everywhere in documentation to enforce using std::ref.
This commit is contained in:
parent
961ccca934
commit
23f6e68d34
2 changed files with 43 additions and 12 deletions
|
|
@ -39,15 +39,19 @@
|
||||||
* foundry.selectors.add< eoStochTournamentSelect<EOT> >( 0.5 );
|
* foundry.selectors.add< eoStochTournamentSelect<EOT> >( 0.5 );
|
||||||
* @endcode
|
* @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
|
* 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:
|
* by indicating their index, just like the foundry was a array of five elements:
|
||||||
* @code
|
* @code
|
||||||
* foundry = {0, 1, 2, 0, 3};
|
* foundry = {0, 1, 2, 0, 3};
|
||||||
* // ^ continue
|
* // ^ ^ ^ ^ ^ replacement
|
||||||
* // ^ crossover
|
* // | | | + selection
|
||||||
* // ^ mutation
|
* // | | + mutation
|
||||||
* // ^ selection
|
* // | + crossover
|
||||||
* // ^ replacement
|
* // + continue
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @note: by default, the firsts of the five operators are selected.
|
* @note: by default, the firsts of the five operators are selected.
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,11 @@ class eoForgeInterface
|
||||||
*
|
*
|
||||||
* This allows for creating containers of pre-parametrized operators (@see eoForgeVector).
|
* 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
|
* @code
|
||||||
eoForgeOperator<eoselect<EOT>,eoRankMuSelect<EOT>> forge(mu);
|
eoForgeOperator<eoselect<EOT>,eoRankMuSelect<EOT>> forge(mu);
|
||||||
// ^ desired ^ to-be-instanciated ^ operator's
|
// ^ desired ^ to-be-instanciated ^ operator's
|
||||||
|
|
@ -101,8 +106,10 @@ template<class Itf, class Op, typename... Args>
|
||||||
class eoForgeOperator : public eoForgeInterface<Itf>
|
class eoForgeOperator : public eoForgeInterface<Itf>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoForgeOperator(Args&&... args) :
|
// Use an additional template to avoid redundant copies of decayed Args variadic.
|
||||||
_args(std::forward<Args>(args)...),
|
template<class ...Args2>
|
||||||
|
eoForgeOperator(Args2... args) :
|
||||||
|
_args(std::forward<Args2>(args)...),
|
||||||
_instanciated(nullptr)
|
_instanciated(nullptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
@ -131,7 +138,7 @@ class eoForgeOperator : public eoForgeInterface<Itf>
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::tuple<Args&&...> _args;
|
std::tuple<Args...> _args;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Metaprogramming machinery which deals with arguments lists @{ */
|
/** Metaprogramming machinery which deals with arguments lists @{ */
|
||||||
|
|
@ -182,6 +189,11 @@ class eoForgeOperator<Itf,Op> : public eoForgeInterface<Itf>
|
||||||
* @note You can actually store several instances of the same class,
|
* @note You can actually store several instances of the same class,
|
||||||
* with different parametrization (or not).
|
* 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.
|
* @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
|
* The default is set to disable the cache, because its use with operators
|
||||||
* which hold a state will lead to unwanted behaviour.
|
* which hold a state will lead to unwanted behaviour.
|
||||||
|
|
@ -225,11 +237,20 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/** Add an operator to the list.
|
/** 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<class Op, typename... Args>
|
template<class Op, typename... Args>
|
||||||
void add(Args&&... args)
|
void add(Args... args)
|
||||||
{
|
{
|
||||||
auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(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<Itf,Op,std::decay_t<Args>...>(
|
||||||
|
std::forward<Args>(args)...);
|
||||||
this->push_back(pfo);
|
this->push_back(pfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,15 +264,21 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Change the set up arguments to the constructor.
|
/** 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..
|
* @warning The operator at `index` should have been added with eoForgeVector::add already..
|
||||||
*/
|
*/
|
||||||
template<class Op, typename... Args>
|
template<class Op, typename... Args>
|
||||||
void setup(size_t index, Args&&... args)
|
void setup(size_t index, Args... args)
|
||||||
{
|
{
|
||||||
assert(index < this->size());
|
assert(index < this->size());
|
||||||
delete this->at(index); // Silent on nullptr.
|
delete this->at(index); // Silent on nullptr.
|
||||||
auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(args)...);
|
auto pfo = new eoForgeOperator<Itf,Op,std::decay_t<Args>...>(
|
||||||
|
std::forward<Args>(args)...);
|
||||||
this->at(index) = pfo;
|
this->at(index) = pfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue