如何使用integer_sequence创建std::initializer_list?

huangapple go评论85阅读模式
英文:

How to create std::initializer_list with integer_sequence?

问题

我有一个整数序列,并且需要为std::map的构造函数创建std::initializer_list。思路如下:

template<uint8_t... Indices>
static constexpr auto GenerateRegMap(std::integer_sequence<uint8_t, Indices...>)
    -> std::initializer_list<std::pair<uint8_t const, uint8_t>>
{
    return {{Indices, 0}...};
}

constexpr auto s = std::integer_sequence<uint8_t, 2, 4, 5, 7, 8, 10, 11, 13, 15>{};
std::map<uint8_t, uint8_t> m (GenerateRegMap(s));
std::cout << m.size() << std::endl;
for (const auto &pair : m)
{
    std::cout << static_cast<int>(pair.first) << " has value " << static_cast<int>(pair.second) << std::endl;
}

在这里,std::initializer_list通常是生成的,但不能返回它:它使用本地存储。我无法想象如何在原地编写GenerateRegMap的内容。

实际上,m是某个类的私有字段,并且最好在成员初始化列表中初始化它。

为什么我不从GenerateRegMap中返回std::map<uint8_t, uint8_t>?因为我遇到了一个错误:constexpr函数不能具有非文字类型的返回类型。

英文:

I have an integer_sequence and I need to create std::initializer_list for constructor of std::map. The idea is below:

template&lt;uint8_t... Indices&gt;
static constexpr auto GenerateRegMap(std::integer_sequence&lt;uint8_t, Indices...&gt;)
    -&gt; std::initializer_list&lt;std::pair&lt;uint8_t const, uint8_t&gt;&gt;
{
    return {{Indices, 0}...};
}

constexpr auto s = std::integer_sequence&lt;uint8_t, 2, 4, 5, 7, 8, 10, 11, 13, 15&gt;{};
std::map&lt;uint8_t, uint8_t&gt; m (GenerateRegMap(s));
std::cout &lt;&lt; m.size() &lt;&lt; std::endl;
for (const auto &amp;pair : m)
{
    std::cout &lt;&lt; static_cast&lt;int&gt;(pair.first) &lt;&lt; &quot; has value &quot; &lt;&lt; static_cast&lt;int&gt;(pair.second) &lt;&lt; std::endl;
}

There std::initializer_list is normally generated, but it cannot be returned: it uses local storage. I cannot imagine how to write the content of GenerateRegMap in place.

Really m is private field of some class and it would be nice to init it in the member initializer list.

Why don't I return std::map&lt;uint8_t, uint8_t&gt; from GenerateRegMap? Because I've got an error: a constexpr function cannot have a nonliteral return type.

答案1

得分: 2

不要回答我要翻译的问题。

以下是要翻译的内容:

"Instead of returning a local initializer_list from the GenerateRegMap, you can use C++14 variable template to generate the initializer_list directly

template<uint8_t... Indices>
constexpr std::initializer_list<std::pair<uint8_t const, uint8_t>> my_list = 
  {{Indices, 0}...};

constexpr auto s = my_list<2, 4, 5, 7, 8, 10, 11, 13, 15>;

std::map<uint8_t, uint8_t> m(s);

If you want the variable template to take integer_sequence as the template type, you can use template partial specialization to get values of integer_sequence to initialize initializer_list, for example

using L = std::initializer_list<std::pair<uint8_t const, uint8_t>>;
template<class Seq>
constexpr L my_list = {};
template<class Seq>
constexpr L my_list<const Seq> = my_list<Seq>;
template<uint8_t... Indices>
constexpr L my_list<std::integer_sequence<uint8_t, Indices...>> = {{Indices, 0}...};

This enables you to generate initializer_list with pre-defined integer_sequence

constexpr auto s = std::integer_sequence<uint8_t, 2, 4, 5, 7, 8, 10, 11, 13, 15>{};
std::map<uint8_t, uint8_t> m(my_list<decltype(s)>);

"

英文:

Instead of returning a local initializer_list from the GenerateRegMap, you can use C++14 variable template to generate the initializer_list directly

template&lt;uint8_t... Indices&gt;
constexpr std::initializer_list&lt;std::pair&lt;uint8_t const, uint8_t&gt;&gt; my_list = 
  {{Indices, 0}...};

constexpr auto s = my_list&lt;2, 4, 5, 7, 8, 10, 11, 13, 15&gt;;

std::map&lt;uint8_t, uint8_t&gt; m(s);

If you want the variable template to take integer_sequence as the template type, you can use template partial specialization to get values of integer_sequence to initialize initializer_list, for example

using L = std::initializer_list&lt;std::pair&lt;uint8_t const, uint8_t&gt;&gt;;
template&lt;class Seq&gt;
constexpr L my_list = {};
template&lt;class Seq&gt;
constexpr L my_list&lt;const Seq&gt; = my_list&lt;Seq&gt;;
template&lt;uint8_t... Indices&gt;
constexpr L my_list&lt;std::integer_sequence&lt;uint8_t, Indices...&gt;&gt; = {{Indices, 0}...};

This enables you to generate initializer_list with pre-defined integer_sequence

constexpr auto s = std::integer_sequence&lt;uint8_t, 2, 4, 5, 7, 8, 10, 11, 13, 15&gt;{};
std::map&lt;uint8_t, uint8_t&gt; m(my_list&lt;decltype(s)&gt;);

huangapple
  • 本文由 发表于 2023年1月9日 13:08:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75053388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定