Использовать производный класс в качестве значения параметра по умолчанию

Мне нужен статический метод моего 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());
};

0

Решение

Вы можете делать объявления несколько раз, поэтому может помочь следующий обходной путь:

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)); }
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]