此问题从here开始,与通过模板定义元组元素时访问元组元素有关。
如果我有访问元组内容的方法:
#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&amp; pd2应设置为指向相应的派生元素(如果它们在System的声明中指定时存在),否则它们应设置为null。
当我这样做时,这是有效的:
System<DerivedElement1<>, DerivedElement2<>> sys; // sys.pd1 points to DerivedElement1<> element of tuple, sys.pd2 points to DerivedElement2<> within tuple
但是,如果我向System的声明提供变量,pd1&amp; pd2都设置为nullptr。
System<DerivedElement1<5>, DerivedElement2<6>> sys; // sys.pd1 == nullptr, sys.pd2 == nullptr
我如何获得pd1&amp; pd2指向正确的元组元素吗?
编辑以试图更清楚:
从公共类派生的不同类型存储在元组中(例如DerivedElement1&lt;&gt;,DerivedElement2&lt; 6&gt;)。我在存储类指针中应该指向元组的派生类元素。当我不使用模板参数时(即上例中的DerivedElement1&lt;&gt;),我使用的设置指针代码有效,但在使用模板参数时却没有(例如DerivedElement1&lt; 5&gt;)。
答案 0 :(得分:1)
所以你需要而不是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
}
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 {};
最后:
// 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)))
};
注意:由于DerivedElement1<N1>
和DerivedElement1<N2>
是不同的类型(对于N1 != N2
),唯一可能的成员类型是基类。
这里你有正确类型的getter方法(或当元素不存在时nullptr_t
。)
注意:给定的谓词不支持DerivedElement1<N>
的派生类。