Этот вопрос следует из here и связан с доступом к элементам кортежа, когда элементы кортежа определяются с помощью шаблона.C++ Variadic Template Параметр и кортеж Iteration
Если у меня есть как средство доступа к содержимому кортежа:
#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;
}
}
Я хочу получить доступ к элементам кортежа здесь, но где каждый элемент кортежа создается с помощью шаблона. Таким образом:
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 должен быть установлен, чтобы указать на соответствующих производных элементов, если они существуют, когда это указано в объявлении системы, в противном случае они должны быть установлены в нуль.
Это работает, когда я делаю:
System<DerivedElement1<>, DerivedElement2<>> sys; // sys.pd1 points to DerivedElement1<> element of tuple, sys.pd2 points to DerivedElement2<> within tuple
Но если поставить переменную в декларации системы, pd1 & pd2 оба установлены в nullptr.
System<DerivedElement1<5>, DerivedElement2<6>> sys; // sys.pd1 == nullptr, sys.pd2 == nullptr
Как я могу получить pd1 & PD2, чтобы указать на правильные элементы кортежа, пожалуйста?
Редактировать, чтобы попытаться быть более ясным:
Различные типы, выведенные из общего класса, хранятся в виде кортежа (например DerivedElement1 <> DerivedElement2 < 6>). У меня есть указатели класса хранилища, которые должны указывать на элементы производного класса кортежа. Устанавливаемый код указателя у меня работает, когда я не использую параметры шаблона (т. Е. DerivedElement1 <> в приведенном выше примере), но не используется, когда я использую параметр шаблона (например, DerivedElement1 < 5>).
Вам либо нужно упростить пример, либо показать фактический код, потому что это достаточно запутанно и неполно, как оно стоит. – AJG85
Я боюсь, что это так просто, как и получается, и я не могу опубликовать настоящий код: по какой-то причине (и я думаю, что это потому, что я поставляю параметр шаблона, а не по умолчанию), обращаясь к элементу кортежа сбой, и я возвращаю nullptr. – John
Он также не компилируется, поскольку вы передаете шаблоны DerivedElement1 и DerivedElement2 в подробности :: get_index, который ожидает параметр типа, а не параметр шаблона. –