Pole na podstawie szablonu - konstruktor

0
class Child_1
{
public:
	Child_1(int a, int c, int e)
	{

	}
};

class Child_2
{
public:
	Child_2(int b, int d)
	{

	}
};

class Child_3
{
public:
	Child_3(int c, int d, int e)
	{

	}
};

template<typename T>
class Parent
{
public:
	int A, B, C, D, E;
	T Child;
	Parent(int a, int b, int c, int d, int e) : 
		A(a), B(b), C(c), D(d), E(e),
		Child(???)
	{

	}
};

class ParentDerived : public Parent<Child_1>
{

};

Mam sytuację jak powyżej. Klasa tworzy pole z szablonu na podstawie innej klasy (lista możliwości jest zamknięta i odgórnie znana). Wszystkie parametry potrzebne do inicjalizacji tego szablonowego pola pochodzą z innych pól klasy Parent (więc nie ma sensu podawać ich z zewnątrz przy tworzeniu ParentDerived), ale każda z klas możliwych do użycia w szablonie potrzebuje trochę innych parametrów (jak widać w przykładzie powyżej). Jak to najlepiej rozwiązać? Ja póki co zrobiłem to tak, że każda z tych klas Child ma taki sam konstruktor i po prostu przyjmuje wszystkie 5 parametrów, ale używa tylko tych, które faktycznie są jej potrzebne. Czy takie rozwiązanie jest ok? Można (powinno się?) to zrobić inaczej?

2

Najprościej to dodać overload konstruktora do każdego Child_X, który przyjmie wszystkie parametry.

Trochę niepokojące jest to, że Child_X mają parametry o nieznanym wzorcu, raz jest to: a c e innym razem: b d i jeszcze c d e.
Na jakiej podstawie szablon miąłby rozstrzygnąć, które zmienne należy przekazać, skoro nawet człowiek nie widzi wzorca.
Jeśli to by było coś w stylu użyj X pierwszych parametrów, to wtedy sytuacja jest jasna i da się zrobić.

Jeśli Child_X są ściśle zadane, a nie jest to cześć API (np klasa podana przez użytkownika twojej biblioteki), to rozwiązanie z overloadem konstrultora jest Ok.
Jeśli ma być to rozwiązanie uniwersalne, gdzie Child_X nie jest z góry znane, to potrzebna jest jakaś jasna regułą, które parametry należy przekazać.

0

@alagner: czemu skasowałeś swoją odpowiedź? Była OK.

0

@MarekR22

Wydaje mi się, że nie. Będąc precyzyjnym, u mnie wygląda to tak:

Core<Direct3D<D3D_Voxel, D3D_Raycast>>

gdzie np. Direct3D też jest szablonem i ma postać:

template<typename... Addons>
	class Direct3D : public Direct3D_Base, public Addons...
	{
	public:
		inline Direct3D(parametry) :
			Direct3D_Base(parametry),
			Addons(Direct3D_Base::Buffer)... {}
	};

Czyli renderer najpierw musi zostać zmontowany przy pomocy bazy (tutaj Direct3D_Base) oraz ewentualnie dodatkowych modułów, np. do obsługi raycastingu albo fizyki voxelowej. Wszystkie moduły zostały napisane tak, że jako parametr przyjmują zawsze tylko referencję do buffora klatki, więc można im je podać jako variadic argument.

0
struct Params { int a,b,c,d,e; }

class Child_1
{
public:
    Child_1(const Params &p):a(p.a),c(p.c),e(p.e)
    {

    }
};

class Child_2
{
public:
    Child_2(const Params &p):b(p.b),d(p.d)
    {

    }
};

class Child_3
{
public:
    Child_3(const Params &p):c(p.c),d(p.d),e(p.e) 
    {

    }
};

template<typename T>
class Parent
{
public:
    int A, B, C, D, E;
    T Child;
    Parent(int a, int b, int c, int d, int e) : 
        A(a), B(b), C(c), D(d), E(e),
        Child(Params{a,b,c,d,e})
    {

    }
};

1 użytkowników online, w tym zalogowanych: 0, gości: 1