在C++17中,聚合初始化将能够初始化公共基类。因此,您可以使用继承+包扩展来构建这样的类。为了使其与结构化绑定配合使用,您必须公开元组接口:专门化
std::tuple_size
和
std::tuple_element
,并为您的类提供
get
函数。
#include <utility>
#include <tuple>
namespace rw {
namespace detail {
template <size_t index, typename T>
struct many_holder
{ T value; };
template <typename idx_seq, typename... Types>
struct many_impl;
template <size_t... Indices, typename... Types>
struct many_impl<std::index_sequence<Indices...>, Types...>: many_holder<Indices, Types>...
{};
}
template <typename... Types>
struct many: detail::many_impl<typename std::make_index_sequence<sizeof...(Types)>, Types...>
{};
template<size_t N, typename... Types>
auto get(const rw::many<Types...>& data) -> const std::tuple_element_t<N, rw::many<Types...>>&
{
const rw::detail::many_holder<N, std::tuple_element_t<N, rw::many<Types...>>>& holder = data;
return holder.value;
}
}
namespace std {
template <typename... Types>
struct tuple_size<rw::many<Types...>> : std::integral_constant<std::size_t, sizeof...(Types)>
{};
template< std::size_t N, class... Types >
struct tuple_element<N, rw::many<Types...> >
{ using type = typename tuple_element<N, std::tuple<Types...>>::type; };
}
#include <iostream>
#include <string>
int main()
{
rw::many<int, std::string, int> x = {42, "Hello", 11};
std::cout << std::tuple_size<decltype(x)>() << '\n' << rw::get<1>(x);
}
Demo (目前只能在clang 3.9中运行):http://melpon.org/wandbox/permlink/9NBqkcbOuURFvypt
注:
- 演示中有一个已注释掉的
nth_type
实现,您可以使用它直接实现tuple_element
而不将其推迟到tuple_element<tuple>
实现中。
get<many>
应该是many
的成员函数或放置在相关联的命名空间中才能使结构化绑定正常工作。您不应重载std::get
(无论如何都会导致未定义行为)。
- 我留下了非const引用和右值引用的
get
实现作为读者的练习。
- 没有使用结构化绑定和指南的示例,因为clang不支持它们(事实上,我不知道任何支持它们的编译器)。理论上
template<typename... Types> many(Types...) -> many<Types...>;
应该可行。
using
、命名空间别名和其他问题了。 - Revolver_Ocelotauto [a, b, c] = ...;
。 - ildjarn