Variadic Templates - dziedziczenie po wybranych elementach z paczki

0

Zastanawiam się, czy możliwe jest stworzenie takiego szablonu, który pozwoli na utworzenie klasy dziedziczącej tylko po wybranych typach z paczki parametrów, zamiast z całości.

template<typename... T>
class Base : public T...
{
};

Da się to zmodyfikować tak, żeby najpierw rozpakować paczkę, a dopiero potem wybrać sobie po których typach klasa ma dziedziczyć (choćby w formie rekurencji)? A może jest na to jakiś inny sposób niż vriadic templates?

4

Dać się da, ale zastanawiam się nad celem takiego pomysłu

Tak na szybko naklepałem coś takiego:

namespace detail
{

template<typename, typename = void>
struct should_inherit : std::false_type {};

template<typename T>
struct should_inherit<T, std::void_t<typename T::foo>> : std::true_type {};

template<typename T, bool = true>
struct conditional_inherit : T {};

template<typename T>
struct conditional_inherit<T, false> {};

}

template<template <typename> typename Pred, typename T>
struct conditional_inherit : detail::conditional_inherit<T, Pred<T>::value>
{};

i przykład:


struct A{ using foo = int; };
struct B{ using foo = double; };
struct C{ using bar = char; };

template<typename... Ts>
struct test_ci : conditional_inherit<detail::should_inherit, Ts>...
{};

using test = test_ci<A,B,C>;

int main()
{
    test t;
    A& a = t;
    B& b = t;
    // C& c = t; // nope
}

https://wandbox.org/permlink/1ZecMq2ct3jmqfBL

0

Dziękuję za odpowiedź, aczkolwiek chodziło mi o nieco inny efekt (ale to moja wina, bo opisałem za mało dokładnie), polegający na customizacji pól klasy. Można to zrobić tak:

template<typename... Pack>
struct EmptyField : public Pack... {};

template<typename Field1, typename Field2>
class Base
{
protected:
	Field1 F1;
	Field2 F2;
};

a potem

Base<EmptyField<Item1, Item2>, EmptyField<Item3, Item4>> base;

A mnie zastanawia, czy dałoby się to rozwiązać w taki sposób, że tworzenie klasy wyglądałoby tak:

Base<Item1, Item2, Item3, Item4> base;

W taki sposób, by Base potrafiło "inteligentnie" przypisać typy do odpowiednich pól, że jak Item1 i Item2 to do F1, a jak Item3 i Item4 to wtedy do F2, a jak coś jeszcze innego, to się tego po prostu nie uwzględnia. Czyli niejako należałoby jedną paczkę parametrów rozbić na mniejsze i na ich bezie stworzyć klasy (wedle szablonu EmptyField), a potem przypisać je do pól w szablonie Base. To osiągalne?

0

To już było i powiedziano ci że to bez sensu a nawet powiedziano czemu.
Czemu wciąż drążysz temat?

1

Ok, teraz zupełnie nie rozumiem co chcesz osiągnąć. Może podaj jakiś rzeczywisty przykład. Poza tym, to wygląda trochę jak robota dla std::tuple z odpowiednim filtrem.

0

Czy ja dobrze rozumiem:

struct Base<>
{};

struct  Base<T1>
{ T1 m1; };

struct  Base<T1, T2>
{ T1 m1; T2 m2;};

i tak dalej? To coś takiego ma być?
No to pytanie... po co, skoro i tak te typy musisz wpisać. Bo to na XY wygląda.

1

Typowy problem XY.
Napisz jaki problem ma rozwiązywać ten kod, a nie jak naprawić twój pomysł na rozwiązanie tego tajemniczego problemu.

0

Nie nazwałbym tego problemem per se, to raczej próba stworzenia dynamicznego interface'u. Mam klasę główną Core i z jej poziomu można się dostać do wszystkiego co oferuje framework (game engine). Czyli np. Core.Graphics.G2D, Core.Controls.Keyboard. Chodzi o możliwość modularnego podejścia do interfac'u, by można było rozszerzać go o niezbędne funkcje w miarę potrzeb, np. tworząc klasę Core<Keyboard, G3D>, by dzięki temu uzyskać dostęp do obsługi klawiatury i renderowania 3D, które nie są domyślnie dostępne.

1

Co za problem dziedziczyć/zawierać? Zresztą jak musisz templatkować to po prostu użyj specjalizacji explicite, przecież nie będziesz mieć bazyliarda tych modułów.

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