std::initializer 列表<> 的静态副本?

问题描述

我一直在尝试制作 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_;
  }
};

这仍然不理想,但足以满足我的需求。