Heterogenous storage of variadic class parameter member variables - c++

I have a variadic class template that is used to create a top-level class for a variable number of classes. Each class that is to go in the top-level class is derived from a base class, as there is common functionality for them. I don't know the best way to store the derived classes in the parent class, but still be able to access the full functionality of the derived class.
If I store the variadic args in a vector, they'll all be stored as a base class and I can't access the derived functionality. If I store them in a tuple, I can't work out how to access the functions by derived type. If I try to access them as discussed here on SO then make_unique isn't available (C++14?).
So, I want to do the following:
class BaseElement {
public:
virtual int polymorphicFunction() {return 0;};
};
class DerivedElement1 : public BaseElement {
public:
virtual int polymorphicFunction() {return 1;};
}
class DerivedElement2 : public BaseElement {
public:
virtual int polymorphicFunction() {return 2;};
}
template<typename... systems> // systems will always be of derived class of BaseElement
class System {
System() : subsystems(systems{}...) {} ; // all variadic elements stored in tuple
// tuple used below, the system elements don't need to be stored in a container, I just want to access them
// I'd be happy to use a vector or access them directly as a member variable
// provided that I can access the derived class. I can't use RTTI.
const std::tuple<systems...> subSystems;
// pointer or reference, I don't mind, but pd1/2 will always exist,
// (but perhaps be NULL), even if there is no derived element passed to the template parameter
DerivedElement1 *pd1;
DerivedElement2 *pd2;
};
//Desired usage
System<DerivedElement1> sys; // sys->pd1 == &derivedElement1WithinTuple, sys->pd2 == NULL
System<DerivedElement2> sys; // sys->pd2 == &derivedElement2WithinTuple, sys->pd2 == NULL
System<DerivedElement1, DerivedElement2> sys; // sys->pd1 == &derivedElement1WithinTuple, sys->pd1 == &derivedElement1WithinTuple
Does anyone have any suggestions as to how I might achieve this please?

With:
#include <cstdint>
#include <type_traits>
#include <tuple>
namespace detail
{
template <typename T, typename... Ts> struct get_index;
template <typename T, typename... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename Tail, typename... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};
template <typename T>
struct get_index<T> : std::integral_constant<std::size_t, 0> {}; // Not found
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>& t) noexcept
-> typename std::enable_if<N < sizeof...(Ts), decltype(&std::get<N < sizeof...(Ts) ? N : 0>(t))>::type
{
return &std::get<N>(t);
}
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>&) noexcept
-> typename std::enable_if<sizeof...(Ts) <= N, nullptr_t>::type
{
return nullptr;
}
}
You may have:
template <typename... systems>
class System {
public:
constexpr System() :
subSystems(),
pd1(detail::safe_get<detail::get_index<DerivedElement1, systems...>::value>(subSystems)),
pd2(detail::safe_get<detail::get_index<DerivedElement2, systems...>::value>(subSystems))
{}
const std::tuple<systems...> subSystems;
const DerivedElement1 *pd1;
const DerivedElement2 *pd2;
};

Related

Correct variadic pack expansion

I am working on C++20 implementation of tuple:
template<size_t INDEX, typename T>
struct wrap { [[no_unique_address]] T data {}; };
template<typename...>
class base {};
template<size_t... INDEX, typename... Ts>
class base<index_sequence<INDEX...>, Ts...> : public wrap<INDEX, Ts>... {
public:
constexpr base( const Ts &... args ) : /* !! HERE SHALL THE MAGIC COME */ {}
};
template<typename... Ts>
class tuple : public base<index_sequence_for<Ts...>, Ts...> {
public:
/* Inherit base constructors */
using base<index_sequence_for<Ts...>, Ts...>::base;
};
My question is: How to correctly implement the code in place of /* !! HERE SHALL THE MAGIC COME */ to call base, means wrap<> constructor - the wrap copy constructor taking the corresponding instance of T (expanded from base's template variadic pack Ts) hold in args?
Thanks in advance to anyone willing to help.
Parameter pack expansion also applies to member initializer lists, so you can simply do this:
template<size_t INDEX, typename T>
struct wrap { [[no_unique_address]] T data {}; };
template<typename...>
class base {};
template<size_t... INDEX, typename... Ts>
class base<std::index_sequence<INDEX...>, Ts...> : public wrap<INDEX, Ts>... {
public:
constexpr base(const Ts&... args) : wrap<INDEX, Ts>{args}... {}
};
Demo.

Detecting a member function in a class which uses CRTP

I am trying to customize a base classes' implementation based on the functions available in a child class using CRTP.
Basic idea of what I want:
// has_inc_function<Child, void> should detect the presence of a member function void Child::inc()
template<class Child, bool = has_inc_function<Child, void>::value>
struct base
{
// ... base implementation stuff
};
template<class Child>
struct base<Child, true>
{
// ... base specialization implementation stuff
};
struct empty : public base<empty>
{};
struct has_inc
{
void inc()
{}
};
struct has_inc_and_crtp : public base<has_inc_and_crtp>
{
void inc()
{}
};
struct has_inc_and_misuse_crtp : public base<has_inc_and_misuse_crtp, true>
{
void inc()
{}
};
struct has_inc_and_misuse_crtp2 : public base<has_inc_and_misuse_crtp, false>
{
void inc()
{}
};
struct no_inc_and_misuse_crtp : public base<no_inc_and_misuse_crtp, true>
{
};
int main()
{
static_assert(has_inc_function<empty, void>::value == false, "");
static_assert(has_inc_function<has_inc, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_misuse_crtp, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_misuse_crtp2, void>::value == true, "");
static_assert(has_inc_function<no_inc_and_misuse_crtp, void>::value == false, "");
}
I've tried a variety of different implementations for has_inc_function<Child, void>, but all of them seem to fail on the case has_inc_and_crtp, and I can't figure out why. I tested with several different compilers via Compiler Explorer, and they all seem to give the same results.
How would I implement has_inc_function so that it works as I would expect in all these test case, or is what I want just not possible?
Implementations I've tried
jrok's solution (Compiler Explorer link):
template <class C, class Ret>
struct has_increment<C, Ret>
{
private:
template <class T>
static constexpr auto check(T*) -> typename std::is_same<
decltype(std::declval<T>().inc()), Ret>::type;
template <typename> static constexpr std::false_type check(...);
typedef decltype(check<C>(nullptr)) type;
public:
static constexpr bool value = type::value;
};
TartanLlama's solution (Compiler Explorer link):
note: that is implementation doesn't match the return type. I've also included sample implementations of stuff in Library fundamentals TS v2 to make this work in C++14
struct nonesuch
{
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
namespace detail {
template <class Default, class AlwaysVoid,
template<class...> class Op, class... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <class Default, template<class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
using value_t = std::true_type;
using type = Op<Args...>;
};
} // namespace detail
template <template<class...> class Op, class... Args>
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template <template<class...> class Op, class... Args>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
template <class Default, template<class...> class Op, class... Args>
using detected_or = detail::detector<Default, void, Op, Args...>;
template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> { };
template <typename T>
using has_type_t = typename T::inc;
template <typename T>
using has_non_type_t = decltype(&T::inc);
template <typename T, class RetType>
using has_inc_function =
disjunction<is_detected<has_type_t, T>, is_detected<has_non_type_t, T>>;
Valentin Milea's solution (Compiler Explorer Link):
template <class C, class RetType>
class has_inc_function
{
template <class T>
static std::true_type testSignature(RetType (T::*)());
template <class T>
static decltype(testSignature(&T::inc)) test(std::nullptr_t);
template <class T>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
Boost TTI (I couldn't figure out how to get Boost to work with Compiler Explorer):
#include <boost/tti/has_member_function.hpp>
BOOST_TTI_TRAIT_HAS_MEMBER_FUNCTION(has_inc_function, inc);
What you want is in this form plainly not possible. The parent of a class has to be known before the class is complete, and hence before it is known whether the class has such a member function or not.
What you can do is a bit dependent on how different the different instantiations of base are. If they are basically the same interface with different implementation details, you can write another class that has the same interface and a variant member (std::variant is sadly C++17, but you could do the same with dynamic polymorphism) to which all calls are forwarded. Then the decision which to use can be done when instantiating.
You could also try something in this direction:
#include <type_traits>
#include <iostream>
template<class Child>
struct base {
int foo();
};
struct has_inc: base<has_inc> {
void inc();
};
struct has_not_inc: base<has_not_inc> {
};
template<class Child, class = std::void_t<decltype(std::declval<Child>().inc())>>
struct mock {
int foo(base<Child>*) { return 1;}
};
template<class Child>
struct mock<Child> {
int foo(base<Child>*) { return 0;}
};
template<class Child>
int base<Child>::foo() {
return mock<Child,void>().foo(this);
}
int main() {
has_inc h;
has_not_inc n;
std::cout << h.foo() << " " << n.foo() << '\n';
}
Here you only use the complete child of type in the definition, not in the declaration. To the point of the definition, the complete child is available, which it was not during declaration.
There are also other ways (I think, everything is not that easy) and what you can use really depends on your use-case, I would think.
PS: std::void_t is C++17, but it is only template<class...> using void_t = void;.
I've tried a variety of different implementations for has_inc_function<Child, void>, but all of them seem to fail on the case has_inc_and_crtp, and I can't figure out why.
The problem (if I understand correctly) is that, in the has_inc_and_crpt case, the value of has_inc_function is first evaluated to determine the default value for the Childs second template parameter
template<class Child, bool = has_inc_function<Child, void>::value>
struct base
that is when Child (that is has_inc_and_crpt) is still incomplete, so the value if false, and in the following use
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
remain false.
How would I implement has_inc_function so that it works as I would expect in all these test case, or is what I want just not possible?
A quick and dirty solution could be add an additional dummy defaulted template parameter to has_inc_function.
By example
// ................................VVVVVVV dummy and defaulted
template <typename C, typename RT, int = 0>
struct has_inc_function
then use it in base explicating a special (different from the default) parameter
// ........................................................V different from the default
template<class Child, bool = has_inc_function<Child, void, 1>::value>
struct base
So, when you use has_inc_functin in the static assert,
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
the class is different, is evaluated in that moment and has_inc_and_crpt is detected with inc() method.
But this only resolve the problem at test case (static_assert()) level.
Still remain the problem (a problem that I don't how to solve) that, declaring base, the default value remain false. So (I suppose) has_inc_and_crpt still select the wrong base base.
The following is a full compiling example, following the jrok's solution.
#include <type_traits>
template <typename C, typename RT, int = 0>
struct has_inc_function
{
private:
template <typename T>
static constexpr auto check(T *) ->
typename std::is_same<decltype(std::declval<T>().inc()), RT>::type;
template <typename>
static constexpr std::false_type check(...);
using type = decltype(check<C>(nullptr));
public:
/// #brief True if there is an inc member function
static constexpr bool value = type::value;
};
template <typename Child, bool = has_inc_function<Child, void, 1>::value>
struct base
{ };
template <typename Child>
struct base<Child, true>
{ };
struct empty : public base<empty>
{ };
struct has_inc
{ void inc() {} };
struct has_inc_and_crtp : public base<has_inc_and_crtp>
{ void inc() {} };
struct has_inc_and_misuse_crtp : public base<has_inc_and_misuse_crtp, true>
{ void inc() {} };
struct has_inc_and_misuse_crtp2 : public base<has_inc_and_misuse_crtp, false>
{ void inc() {} };
struct no_inc_and_misuse_crtp : public base<no_inc_and_misuse_crtp, true>
{ };
template <typename C, typename RT>
constexpr auto hif_v = has_inc_function<C, RT>::value;
int main ()
{
static_assert(hif_v<empty, void> == false, "");
static_assert(hif_v<has_inc, void> == true, "");
static_assert(hif_v<has_inc_and_crtp, void> == true, "");
static_assert(hif_v<has_inc_and_misuse_crtp, void> == true, "");
static_assert(hif_v<has_inc_and_misuse_crtp2, void> == true, "");
static_assert(hif_v<no_inc_and_misuse_crtp, void> == false, "");
}

std::tuple of std::shared_ptr of template parameter pack

I want to implement a class template that:
behaves like a function
it's input and output variables are all shared.
relatively easy to use.
As a result, I construct the following:
// all input/output variable's base class
class basic_logic_parameter;
// input/output variable, has theire value and iterators to functions that reference to this variable
template <typename FuncIterator, typename ValueType>
class logic_parameter
:public basic_logic_parameter
{
private:
std::list<FuncIterator> _refedFuncs;
ValueType _val;
public:
};
// all `function`'s base class
class basic_logic_function
{
public:
virtual ~basic_logic_function() = 0;
};
// the function, has input/output variable
template <typename FuncIterator, typename R, typename... Args>
class logic_function_base
:public basic_logic_function
{
private:
std::shared_ptr<logic_parameter<FuncIterator, R>> _ret;
std::tuple<std::shared_ptr<logic_parameter<FuncIterator, Args>>...> _args;
public:
template <std::size_t N>
decltype(auto) arg()
{
return std::get<N>(_args);
}
template <std::size_t N>
struct arg_type
{
typedef std::tuple_element_t<N> type;
};
template <std::size_t N>
using arg_type_t = arg_type<N>::type;
decltype(auto) ret()
{
return _ret;
}
};
I wish to use as these like:
// drawing need color and a pen
struct Color
{
};
struct Pen
{
};
struct Iter
{
};
class Drawer
:public logic_function_base<Iter, void(Color, Pen)>
{
public:
void draw()
{
arg_type_t<0> pColor; // wrong
}
}
My compiler can not pass this code through, why? I just want convert a template parameter pack to std::tuple of std::shared_ptr of them.
for example:
Given struct A, int, struct C, I want to have:
std::tuple<
std::shared_ptr<logic_parameter<A>>,
std::shared_ptr<logic_parameter<int>>,
std::shared_ptr<logic_parameter<C>>,
>
The problem (once the small errors are fixed1) is that you instantiate:
logic_function_base<Iter, void(Color, Pen)>
...meaning that FuncIterator is Iter and R is void(Color, Pen), so Args is emtpy <>, so decltype(_args) is an empty std::tuple<>, and your code fails to obtain the type of the 0th element of an empty tuple, which is legit.
What you want is partial specialization of logic_function_base:
template <typename F, typename T>
class logic_function_base;
template <typename FuncIterator, typename R, typename... Args>
class logic_function_base<FuncIterator, R(Args...)>: public basic_logic_function {
};
1 Small mistakes in your current code:
template <std::size_t N>
struct arg_type
{
typedef std::tuple_element_t<N, decltype(_args)> type; // Missing the tuple type
};
template <std::size_t N>
using arg_type_t = typename arg_type<N>::type; // Missing a typename
This may not answer your whole question, but you could use the following trait to wrap tuple element types.
template <typename T> struct wrap;
template <typename... T>
struct wrap<std::tuple<T...>> {
using type = std::tuple<std::shared_ptr<logic_parameter<T>>...>;
}
template <typename T>
using wrap_t = typename wrap<T>::type;
You can then use it like this:
std::tuple<int,double,char> t1;
wrap_t<decltype(t)> t2;
The type of t2 is std::tuple<std::shared_ptr<logic_parameter<int>>,std::shared_ptr<logic_parameter<double>>,std::shared_ptr<logic_parameter<char>>>.

Unpack all variadic template arguments except last one as type of variable

I have a template class that accepts a variable number of types as arguments. The constructor accepts a pointer to an instance of the class that uses Args... - 1 as parameter type. Searching over the internet I found out that a std::tuple is often used to handle this type of problems, but I don't understand how I could take the template arguments, create a tuple, remove the last type and then unpack the tuple again and store the result in a variable that can be retrieved later by the parent() function.
template<typename ...Args>
class MyClass
{
public:
MyClass(MyClass<Args...> *parent) : parent_(parent) // Should be Args - 1
{
}
MyClass<Args...>* parent()
{
return parent_;
}
private:
MyClass<Args...> *parent_;
};
I found different answers here on StackOverflow about similar topics that involve tuples. This code has been posted on another question and should get a tuple with all parameters except the last one. The problem is that I don't know how to adapt it to unpack that tuple again.
template<typename, typename>
struct concat_tuple { };
template<typename... Ts, typename... Us>
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>>
{
using type = std::tuple<Ts..., Us...>;
};
template <class T>
struct remove_last;
template <class T>
struct remove_last<std::tuple<T>>
{
using type = std::tuple<>;
};
template <class T, class... Args>
struct remove_last<std::tuple<T, Args...>>
{
using type = typename concat_tuple<std::tuple<T>, typename remove_last<std::tuple<Args...>>::type>::type;
};
#include <type_traits>
#include <tuple>
#include <utility>
#include <cstddef>
template <template <typename...> class C, typename... Args, std::size_t... Is>
auto pop_back(std::index_sequence<Is...>) noexcept
-> C<std::tuple_element_t<Is, std::tuple<Args...>>...>&&;
template <typename... Args>
class MyClass
{
using Parent = std::remove_reference_t<
decltype(pop_back<::MyClass, Args...>(std::make_index_sequence<sizeof...(Args) - 1>{}))
>;
public:
explicit MyClass(Parent* parent) : parent_(parent)
{
}
Parent* parent()
{
return parent_;
}
private:
Parent* parent_;
};
template <>
class MyClass<> {};
int main()
{
MyClass<> a;
MyClass<int> b(&a);
MyClass<int, char> c(&b);
MyClass<int, char, float> d(&c);
}
DEMO
The answer for the previous question, before the edit:
#include <tuple>
#include <utility>
#include <cstddef>
template <typename... Args>
class MyClass
{
public:
auto newInstance()
{
return newInstance(std::make_index_sequence<sizeof...(Args) - 1>{});
}
private:
template <std::size_t... Is>
MyClass<typename std::tuple_element<Is, std::tuple<Args...>>::type...> newInstance(std::index_sequence<Is...>)
{
return {};
}
};
DEMO 2
Why the pop_back function has no body?
This is actually a trait implemented in terms of a function declaration. Alternatively, you could use a more classic solution with a structure specialization:
template <typename T, typename S>
struct pop_back;
template <template <typename...> class C, typename... Args, std::size_t... Is>
struct pop_back<C<Args...>, std::index_sequence<Is...>>
{
using type = C<std::tuple_element_t<Is, std::tuple<Args...>>...>;
};
and then use:
using Parent = typename pop_back<MyClass, std::make_index_sequence<sizeof...(Args) - 1>>::type;
That is, I used a function declaration to shorten the syntax. And it doesn't require a body, since noone is supposed to call this function in an evaluated context.
Why are you using noexcept?
Imagine you have a function:
void foo(MyClass<int, char>) noexcept {}
And elsewhere you want to check whether the call is noexcept:
static_assert(noexcept(foo(pop_back<MyClass, int, char, float>(std::index_sequence<0, 1>{}))), "!");
Without the noexcept specifier, the above assertion would fail, since the call to pop_back would be considered as possibly throwing code.

C++ Variadic Template Parameter and Tuple Iteration

This question follows on from here and is to do with accessing tuple elements when the elements of the tuple are defined by means of a template.
If I have as a means of accessing the contents of a tuple:
#include <cstdint>
#include <type_traits>
#include <tuple>
namespace detail
{
template <typename T, typename... Ts> struct get_index;
template <typename T, typename... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename Tail, typename... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};
template <typename T>
struct get_index<T> : std::integral_constant<std::size_t, 0> {}; // Not found
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>& t) noexcept
-> typename std::enable_if<N < sizeof...(Ts), decltype(&std::get<N < sizeof...(Ts) ? N : 0>(t))>::type
{
return &std::get<N>(t);
}
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>&) noexcept
-> typename std::enable_if<sizeof...(Ts) <= N, nullptr_t>::type
{
return nullptr;
}
}
I want to access the tuple elements here, but where each tuple element is created by means of a template. Thus:
class BaseElement {
public:
virtual int polymorphicFunction() {return 0;};
};
template <uint32_t exampleParameter = 1>
class DerivedElement1 : public BaseElement {
public:
DerivedElement1() : i(exampleParameter) {}
virtual int polymorphicFunction() {return 1;};
uint32_t i; /// just used as a placeholder to demo use of parameter
}
template <uint32_t exampleParameter = 2>
class DerivedElement2 : public BaseElement {
public:
DerivedElement2() : i(exampleParameter) {}
virtual int polymorphicFunction() {return 2;};
uint64_t i; /// just used as a placeholder to demo use of parameter (class is different to DE1)
}
template<typename... systems> // systems will always be of derived class of BaseElement
class System {
System() : subsystems(systems{}...),
pd1(detail::safe_get<detail::get_index<DerivedElement1, systems...>::value>(subSystems)),
pd2(detail::safe_get<detail::get_index<DerivedElement2, systems...>::value>(subSystems))
{} // all variadic elements stored in tuple
const std::tuple<systems...> subSystems;
DerivedElement1<> *pd1;
DerivedElement2<> *pd2;
};
pd1 & pd2 should be set to point to the respective derived elements if they exist when specified in the declaration of System, otherwise they should be set to null.
This works when I do:
System<DerivedElement1<>, DerivedElement2<>> sys; // sys.pd1 points to DerivedElement1<> element of tuple, sys.pd2 points to DerivedElement2<> within tuple
But if I supply a variable to the declaration of System, pd1 & pd2 are both set to nullptr.
System<DerivedElement1<5>, DerivedElement2<6>> sys; // sys.pd1 == nullptr, sys.pd2 == nullptr
How can I get pd1 & pd2 to point to the correct tuple elements please?
Edit to try to be more clear:
Different types, derived from a common class, are stored in a tuple (e.g. DerivedElement1<>, DerivedElement2<6>). I have within the storage class pointers that should point to the derived class elements of the tuple. The set pointer code I have works when I use no template parameters, (i.e. DerivedElement1<> in the example above), but does not when I use a template parameter (e.g. DerivedElement1<5>).
So you need instead of get_index:
namespace detail
{
template <template<typename> class Pred, typename... Ts> struct get_index_if;
template <template<typename> class Pred, typename T, typename... Ts>
struct get_index_if<Pred, T, Ts...> :
std::integral_constant<
std::size_t,
Pred<T>::value ? 0 : 1 + get_index_if<Pred, Ts...>::value>
{};
template <template<typename> class Pred>
struct get_index_if<Pred> : std::integral_constant<std::size_t, 0> {}; // Not found
}
A predicate for your types for get_index_if:
template <typename T> struct is_a_Derived1 : std::false_type {};
template <std::uint32_t N> struct is_a_Derived1<DerivedElement1<N>> : std::true_type {};
template <typename T> struct is_a_Derived2 : std::false_type {};
template <std::uint32_t N> struct is_a_Derived2<DerivedElement2<N>> : std::true_type {};
And finally:
// helper for trailing return type... until C++14
#define Return(Ret) decltype Ret { return Ret; }
template <typename... systems>
class System {
const std::tuple<systems...> subSystems;
public:
constexpr System() : subSystems() {}
auto getDerivedElement1()
-> Return((detail::safe_get<detail::get_index_if<is_a_Derived1, systems...>::value>(subSystems)))
auto getDerivedElement2()
-> Return((detail::safe_get<detail::get_index_if<is_a_Derived2, systems...>::value>(subSystems)))
};
Note: As DerivedElement1<N1> and DerivedElement1<N2> are different types (for N1 != N2), the only possible member type would be he base class.
Here you have getter methods with correct type (or nullptr_t when element is absent).
Note: the given predicate doesn't support derived class of DerivedElement1<N>.