c++ - 在编译时像未知边界数组一样初始化 C++ 结构

标签 c++ templates c++17 variadic-templates

我可以写这个并且它工作得很好:

struct Foo
{
  int i;
  std::string s;
};

const Foo foo[] = {
  { 42, "the answer to the ultimate questions" },
  { 23 /*initializing only the first member, 's' gets the default value*/ }
};

我想做的是用一个结构来包装数组,这样我就可以向它添加方法:

template<typename V1, typename V2, size_t Count>
struct Map
{
  std::array<std::pair<V1, V2>, Count> mappings;
  //or
  //std::pair<V1, V2> mappings[Count];

  V1 operator()(const V2&) const;
  V2 operator()(const V1&) const;
};

我想将它初始化为一个未知边界数组,如下所示:

constexpr Map<int, std::string_view, /*???*/> = {
  { 42, "the answer to the ultimate question" },
  { 23, "some other stuff" },
  { /*...*/ }
};

但是随后出现了一个问题,您需要指定我不想做的 Count 模板参数,我希望它像在数组情况下一样工作。

我认为返回此类对象的函数可以解决问题,如下所示:

template<typename V1, typename V2, typename... Args>
constexpr auto makeMap(Args... args)
{
  return Map<V1, V2, sizeof...(Args)>{ args... };
}

然后允许像这样使用它:

using Item = std::pair<int, std::string_view>;

constexpr auto map = makeMap<int, std::string_view>(
  Item{ 42, "the answer to the ultimate questions" },
  Item{ 23, "some other stuff" }
);

但是如果你省略了Item类型,那么模板实例化就不能推导参数类型,这就禁止了我最初想要的用法:

constexpr auto map = makeMap<int, std::string_view>(
  { 42, "the answer to the ultimate questions" },
  { 23, "some other stuff" }
);

目前我认为这是不可能的,但无论如何我还是想问一下,以防我遗漏了什么。

在研究这个时,我发现了 a proposal这正是我想要的。

无论如何,我很乐意得到任何想法。

最佳答案

使用建议 to_array :

template<typename V1, typename V2, size_t N>
constexpr auto makeMap(std::pair<V1, V2> const (&a)[N])
{
  return Map<V1, V2, N>{ to_array<std::pair<V1, V2>>(a) };
}

constexpr auto map = makeMap<int, std::string_view>({
  { 42, "the answer to the ultimate question" },
  { 23, "some other stuff" },
  { /*...*/ }
});

如果您的编译器支持 library fundamentals TS v2,您可以找到 to_array 的实现在标题中 <experimental/array> , 在命名空间内 std::experimental .

关于c++ - 在编译时像未知边界数组一样初始化 C++ 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54713474/

相关文章:

c++ - SFINAE 和参数数量

c++ - 对象 vector 的模板字符串表示

c++ - 运算符 << 的两阶段查找

c++ - std::addressof 作为 C++17 中的常量表达式

c++ - static_cast - 兼容类型之间的转换意味着什么?

c++ - Quicksort 按特定成员 C++ 对对象数组进行排序

c++ - 为什么反斜杠作为转义字符而不是较少使用的字符?

c++ - boost 线程和信号处理

c++ - 根据输入从一种类型转换为另一种类型

c++ - C++17 中 std::unordered_map 的推导指南