Question

I need a static method of my Base class to have a default parameter value of type Derived. Is there a way to implement this without use of overloading? (see here).

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

... gives me an error about the usage of the incomplete type Derived. How ever, I cannot place the definition of Derived in front of problem_here because it must be defined after the definition of its base class Base.

Unfortunately, returning a pointer from make_derived is not an option.

Overloading problem_here is the only thing I came up with until now, but as the "real" problem_here method takes 2 (and another one 3) parameters, and it's part of a library, this gives me ...

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"

.. for only the two parameter case.

Is there a way to avoid writing all those function signatures, while still maintaining the same performance (no unneccessary copy/move construction for any parameter constellation) and same behaviour on the caller site?


I should add that there are multiple functions like problem_here and all need access to the protected constructor of Derived (and to those of its many siblings). So the main reason to make these methods static members of Base is to be able to friend class Base; in each of the derived classes instead of friending every function.


Refactoring showed me, that I could move the code accessing the protected constructors of the derived classes into a single factory function. That way, I'm able to move the functions with the default parameters outside Base and let the call the factory. Now I still have to friend every one of those functions, but only a single time (in Base to give them access to the factory). I could circumvent this by placing all functions into a helper class and friending it instead, but that looks like a hack to me.

class Base
{
  friend class Helper; // The Hack
  friend void no_problem_here(Base &&); // No hack, more writting


  protected:
    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());
};
Was it helpful?

Solution

You can make declarations multiple times, so the following workaround might help:

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()) { /* ... */ }

If there's a problem factoring the code like that, you can always insert a little trampoline function:

 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)); }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top