Мне нужен статический метод моего Base
класс, чтобы иметь значение параметра по умолчанию типа Derived
,
Есть ли способ реализовать это без использования перегрузки? (увидеть Вот).
class Base;
class Derived;
Derived make_derived(void);
class Base
{
public:
static void problem_here(Base && = make_derived());
};
class Derived : public Base
{
};
Derived make_derived()
{
return Derived();
}
… выдает ошибку об использовании неполного типа Derived
, Однако я не могу дать определение Derived
перед problem_here
потому что он должен быть определен после определения его базового класса Base
,
К сожалению, возвращая указатель из make_derived
это не вариант.
перегрузка problem_here
это единственное, что я придумал до сих пор, но как «настоящий» problem_here
Метод принимает 2 (и еще 3) параметра, и это часть библиотеки, это дает мне …
static void problem_here(Thing const &, Base const &);
static void problem_here(Thing const &, Base &&);
static void problem_here(Thing const &); // Default param "hack"static void problem_here(Thing &&, Base const &);
static void problem_here(Thing &&, Base &&);
static void problem_here(Thing &&); // Default param "hack"
.. только для случая с двумя параметрами.
Есть ли способ избежать написания всех этих сигнатур функций, сохраняя при этом одинаковую производительность (без ненужной конструкции копирования / перемещения для любого созвездия параметров) и такое же поведение на сайте вызывающей стороны?
Я должен добавить, что есть несколько функций, таких как problem_here
и всем нужен доступ к защищенному конструктору Derived
(и тем из его многочисленных родных братьев). Таким образом, основная причина сделать эти методы статическими членами Base — это возможность friend class Base;
в каждом из производных классов вместо друзей каждой функции.
Рефакторинг показал мне, что я могу переместить код, обращающийся к защищенным конструкторам производных классов, в одну фабричную функцию. Таким образом, я могу переместить функции с параметрами по умолчанию за пределы Base
и пусть звонят на фабрику. Теперь мне по-прежнему приходится дружить с каждой из этих функций, но только один раз (в Base
дать им доступ к заводу). Я мог бы обойти это, поместив все функции в класс помощника и добавив его вместо него, но это выглядит для меня как хак.
class Base
{
friend class Helper; // The Hack
friend void no_problem_here(Base &&); // No hack, more writtingprotected:
static void factory(Thing && from_which_I_can_construct_the_correct_derived_class);
// return type void to keep it simple, move parameter type because special cases
// handled in "trampoline" functions and a copy of the Thing must be stored either
// way.
};
class Derived : public Base
{
friend class Base;
// protected constructor omited for simplicity.
}void no_problem_here(Base && = make_derived());
// ...
void no_problem_here(Base && b)
{
// work, and then call Base::factory
}
// or
class Helper
{
protected:
// Constructors ...
public:
static void no_problem_either(Base && = make_derived());
};
Вы можете делать объявления несколько раз, поэтому может помочь следующий обходной путь:
class Base;
class Derived;
Derived make_derived(void);
class Base
{
public:
static void problem_here(Base &&);
};
class Derived : public Base {};
void Base::problem_here(Base && = make_derived()) { /* ... */ }
Если есть проблема с разложением такого кода, вы всегда можете вставить небольшую функцию батута:
class Base
{
public:
static void problem_here(Base &&);
private:
static void problem_here_impl(Base &&);
};
inline void Base::problem_here(Base && x = make_derived())
{ problem_here_impl(std::move(x)); }
Других решений пока нет …