7
class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name>
{
public:
  MyDerived();
}


MyDerived::MyDerived
: ???(params)
{}

Is there any way to call a base constructor without writing its full name and without typedeffing it?

The reason is clearly to avoid code duplication and introducing multiple positions to change if a detail in the base class template params changes.

Level 2 of this:

template <uint32 C>
class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name>
{
public:
  MyDerived();
}

template <uint32 C>
MyDerived::MyDerived<C> 
: ???(C)
{
}
vlad_tepesch
  • 6,681
  • 1
  • 38
  • 80

2 Answers2

10

You could use injected-class-name. Incredible<...>::Incredible refers to itself, and since MyDerived isn't a class template, unqualified lookup will look in the scope of its base classes:

MyDerived::MyDerived
: Incredble(params)
{}

If Incredible is a dependent name, then you need to qualify it. You can actually simply use the derived type name to qualify the base class's injected-class-name (h/t Johannes Schaub-litb):

MyDerived::MyDerived
: MyDerived::Incredible(params)
{}

This will work in all cases.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    does this change if MyDerived is a classe tempate? because it is for me but the template parameter. i can add this to the initial question – vlad_tepesch Sep 09 '16 at 13:56
  • detail namespaces are always nice. – Hayt Sep 09 '16 at 13:56
  • @vlad_tepesch The answer already addresses this case - you can't use injected-class-name, but you can always add an alias or alias template in a non-public namespace – Barry Sep 09 '16 at 14:37
  • 5
    If it is a class template, `: MyDerived::Incredible(params) { }` should just work. – Johannes Schaub - litb Sep 09 '16 at 23:24
  • 2
    @JohannesSchaub-litb **Wow.** That's the trick I've been missing. That seems superior to all the other solutions here and worthy of its own answer. So qualifying with the derived class name makes the injected base class type visible when the base is a template. I guess that makes sense, given that we have to use `this->` to get at its members, etc. I just might never have thought of trying it without you pointing it out! – underscore_d Sep 10 '16 at 09:35
0

If you don't wont to use using or typedef to avoid "polluting the enclosing namespace", you can use using inside the class/struct.

An example

#include <map>

template <typename ...>
class foo
 {};

struct A : public foo<int, std::tuple<long, char, std::map<std::string, int>>>
 {
   using base_t = foo<int, std::tuple<long, char, std::map<std::string, int>>>;

   A () : base_t{}
    { };
 };

int main()
 { } 
max66
  • 65,235
  • 10
  • 71
  • 111
  • 2
    You used the `Incredble` class name two times. – Liviu Sep 09 '16 at 13:59
  • 1
    @Liviu - that's right; but you can use `base_t` for other purposes in the same class (other constructors, by example); to avoid the duplication you can define `base_t` outside the struct but you pollute the external namespace – max66 Sep 09 '16 at 14:03
  • deriving from stl object is in general no good idea. I mean the idea is OK but the example is bad – Hayt Sep 09 '16 at 14:03
  • @Hayt - I'm agree; modified example. – max66 Sep 09 '16 at 14:09
  • @max66 "you pollute the external namespace" only if you dump the typedef in it without thinking to use a local detail namespace or w/e. – underscore_d Sep 10 '16 at 09:29