构造一个具有任意数量类型的元组,所有类型都可从单一类型构造,并且不可默认构造
Construct a tuple with arbitrary number of types, all constructable from a single type, and non-default-construcible
我有一个元组
using MyTuple = std::tuple<Foo1, Foo2, Foo3, ... FooN>;
并想像这样构造 MyTuple
MyTuple foo{Foo1{x}, Foo2{x}, Foo3{x}, ... FooN{x}};
FooK
不是默认可构造的
N
在写入时未知。因此我不能像上面那样对列表进行硬编码。
我有的是
Enum::Tuple<EnumType, EnumTypeTraits> foo;
这是根据此处的建议构建的:, like so: https://github.com/milasudril/libenum/blob/master/libenum/tuple.hpp。
我是否需要向 Enum::Tuple
添加一些构造函数才能使其正常工作?
这里Enum::Tuple
供参考:
namespace detail
{
template<ContiguousEnum EnumType,
template<EnumType>
class EnumItemTraits,
class T = std::make_integer_sequence<
std::underlying_type_t<EnumType>,
Size<EnumType>::value // NOTE: calling distance here triggers ICE in gcc 10.2
>>
struct make_tuple;
template<ContiguousEnum EnumType,
template<EnumType>
class EnumItemTraits,
std::underlying_type_t<EnumType>... indices>
struct make_tuple<EnumType,
EnumItemTraits,
std::integer_sequence<std::underlying_type_t<EnumType>, indices...>>
{
using type =
std::tuple<typename int_to_type<EnumType, EnumItemTraits, indices>::type...>;
};
}
template<ContiguousEnum EnumType, template<EnumType> class EnumItemTraits>
class Tuple: private detail::make_tuple<EnumType, EnumItemTraits>::type
{
public:
using Base = typename detail::make_tuple<EnumType, EnumItemTraits>::type;
using index_type = EnumType;
template<index_type index>
using traits = EnumItemTraits<index>;
using Base::Base;
static constexpr auto size() { return std::tuple_size_v<Base>; }
template<index_type i>
using tuple_element = std::tuple_element_t<distance(begin(Empty<EnumType>{}), i), Base>;
template<index_type i>
constexpr auto const& get() const
{
return std::get<distance(begin(Empty<EnumType>{}), i)>(base());
}
template<index_type i>
constexpr auto& get()
{
return std::get<distance(begin(Empty<EnumType>{}), i)>(base());
}
private:
Base const& base() const { return *this; }
Base& base() { return *this; }
};
据我了解,您想要这样的东西:
template <typename... Ts> struct tag{};
template <typename Tuple> struct tag_from_tuple;
template <typename Tuple> using tag_from_tuple_t = typename tag_from_tuple<Tuple>::type;
template <typename... Ts> struct tag_from_tuple<std::tuple<Ts...>>
{
using type = tag<Ts...>;
};
template <typename T, typename... Ts>
std::tuple<Ts...> make_tuple_from_impl(const T& t, tag<Ts...>)
{
return {Ts{t}...};
}
template <typename Tuple, typename T>
Tuple make_tuple_from(const T& t)
{
return make_tuple_from_impl(t, tag_from_tuple_t<Tuple>{});
}
我有一个元组
using MyTuple = std::tuple<Foo1, Foo2, Foo3, ... FooN>;
并想像这样构造 MyTuple
MyTuple foo{Foo1{x}, Foo2{x}, Foo3{x}, ... FooN{x}};
FooK
不是默认可构造的N
在写入时未知。因此我不能像上面那样对列表进行硬编码。
我有的是
Enum::Tuple<EnumType, EnumTypeTraits> foo;
这是根据此处的建议构建的:
我是否需要向 Enum::Tuple
添加一些构造函数才能使其正常工作?
这里Enum::Tuple
供参考:
namespace detail
{
template<ContiguousEnum EnumType,
template<EnumType>
class EnumItemTraits,
class T = std::make_integer_sequence<
std::underlying_type_t<EnumType>,
Size<EnumType>::value // NOTE: calling distance here triggers ICE in gcc 10.2
>>
struct make_tuple;
template<ContiguousEnum EnumType,
template<EnumType>
class EnumItemTraits,
std::underlying_type_t<EnumType>... indices>
struct make_tuple<EnumType,
EnumItemTraits,
std::integer_sequence<std::underlying_type_t<EnumType>, indices...>>
{
using type =
std::tuple<typename int_to_type<EnumType, EnumItemTraits, indices>::type...>;
};
}
template<ContiguousEnum EnumType, template<EnumType> class EnumItemTraits>
class Tuple: private detail::make_tuple<EnumType, EnumItemTraits>::type
{
public:
using Base = typename detail::make_tuple<EnumType, EnumItemTraits>::type;
using index_type = EnumType;
template<index_type index>
using traits = EnumItemTraits<index>;
using Base::Base;
static constexpr auto size() { return std::tuple_size_v<Base>; }
template<index_type i>
using tuple_element = std::tuple_element_t<distance(begin(Empty<EnumType>{}), i), Base>;
template<index_type i>
constexpr auto const& get() const
{
return std::get<distance(begin(Empty<EnumType>{}), i)>(base());
}
template<index_type i>
constexpr auto& get()
{
return std::get<distance(begin(Empty<EnumType>{}), i)>(base());
}
private:
Base const& base() const { return *this; }
Base& base() { return *this; }
};
据我了解,您想要这样的东西:
template <typename... Ts> struct tag{};
template <typename Tuple> struct tag_from_tuple;
template <typename Tuple> using tag_from_tuple_t = typename tag_from_tuple<Tuple>::type;
template <typename... Ts> struct tag_from_tuple<std::tuple<Ts...>>
{
using type = tag<Ts...>;
};
template <typename T, typename... Ts>
std::tuple<Ts...> make_tuple_from_impl(const T& t, tag<Ts...>)
{
return {Ts{t}...};
}
template <typename Tuple, typename T>
Tuple make_tuple_from(const T& t)
{
return make_tuple_from_impl(t, tag_from_tuple_t<Tuple>{});
}