fix: use perfect forwarding in forges

- Avoid some cases of implicit copy instead of correct reference
forwarding.
- Use C++-17's make_from_tuple instead of the previous complex machinery.
This commit is contained in:
Johann Dreo 2020-04-26 23:58:03 +02:00
commit d27aad810d

View file

@ -101,8 +101,8 @@ template<class Itf, class Op, typename... Args>
class eoForgeOperator : public eoForgeInterface<Itf> class eoForgeOperator : public eoForgeInterface<Itf>
{ {
public: public:
eoForgeOperator(Args... args) : eoForgeOperator(Args&&... args) :
_args(args...), _args(std::forward<Args>(args)...),
_instanciated(nullptr) _instanciated(nullptr)
{ } { }
@ -120,7 +120,7 @@ class eoForgeOperator : public eoForgeInterface<Itf>
if(_instanciated) { if(_instanciated) {
delete _instanciated; delete _instanciated;
} }
_instanciated = constructor(_args); _instanciated = op_constructor(_args);
} }
return *_instanciated; return *_instanciated;
} }
@ -131,31 +131,15 @@ 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 @{ */
template <int... Idx> template<class T>
struct index {}; Op* op_constructor(T& args)
template <int N, int... Idx>
struct gen_seq : gen_seq<N - 1, N - 1, Idx...> {};
template <int... Idx>
struct gen_seq<0, Idx...> : index<Idx...> {};
template <typename... Ts, int... Idx>
Op* constructor(std::tuple<Ts...>& args, index<Idx...>)
{ {
Op* p_op = new Op(std::get<Idx>(args)...); // FIXME double-check that the copy-constructor is a good idea to make_from_tuple with dynamic storage duration.
_instanciated = p_op; return new Op(std::make_from_tuple<Op>(args));
return p_op;
}
template <typename... Ts>
Op* constructor(std::tuple<Ts...>& args)
{
return constructor(args, gen_seq<sizeof...(Ts)>{});
} }
/** @} */ /** @} */
@ -243,9 +227,9 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
/** Add an operator to the list. /** Add an operator to the list.
*/ */
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...>(args...); auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(args)...);
this->push_back(pfo); this->push_back(pfo);
} }
@ -263,11 +247,11 @@ class eoForgeVector : public std::vector<eoForgeInterface<Itf>*>
* @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...>(args...); auto pfo = new eoForgeOperator<Itf,Op,Args...>(std::forward<Args>(args)...);
this->at(index) = pfo; this->at(index) = pfo;
} }