问题描述
我一直在尝试制作 std::initializer_list
的静态副本并想出了这个:
template <typename A>
class static_list
{
A* p_;
std::size_t const N_;
static inline unsigned c_{};
template <unsigned UID,typename T,std::size_t N>
static inline T storage_[N];
public:
static_list(std::initializer_list<A> const a):
N_(a.size())
{
p_ = [&]<auto ...I,auto ...J>(std::size_t const n,std::index_sequence<I...>,std::index_sequence<J...>)
{
A* ptr{};
auto const f([&]<auto K>(std::index_sequence<K>)
{
(
(ptr = J == n ? storage_<K,A,J> : ptr),...
);
}
);
(
(
I == c_ ? f(std::index_sequence<I>()) : (void)0
),...
);
return ptr;
}(a.size(),std::make_index_sequence<50>(),std::make_index_sequence<10>());
++c_;
std::ranges::copy(a,p_);
}
};
这似乎是 work,但是存储要求很糟糕。有没有办法在运行时计算 UID
而不需要用户提供它?我看了__TIME__
、__COUNTER__
和其他技巧。
编辑:
我想要这个:
using pair_t = std::pair<
std::string_view,std::pair<std::string_view,bool>[]
>;
但我不能在一对中存储不确定大小的数组。通常的解决方案是使用 std::vector<>
代替,但这将从堆中分配。这就是我想要解决的。 std::array<>
需要事先知道大小,不应复制 std::initializer_list<>
。
解决方法
最后我选择了这个:
template <typename A>
class static_array
{
A* p_;
std::size_t const N_;
template <auto,std::size_t N>
static inline A storage_[N];
static inline unsigned c_;
public:
template <std::size_t N>
static_array(A (&&a)[N]):
N_(N)
{
[&]<auto ...I>(auto const c,std::index_sequence<I...>)
{
(
(
I == c ? p_ = storage_<I,N> : nullptr
),...
);
}(c_++,std::make_index_sequence<255>());
std::ranges::move(a,p_);
}
static_array(static_array const&) = default;
static_array(static_array&&) = default;
//
auto begin() const noexcept
{
return p_;
}
auto end() const noexcept
{
return p_ + N_;
}
auto size() const noexcept
{
return N_;
}
};
这仍然不理想,但足以满足我的需求。