通过类型检索printf格式参数

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

Retrieving printf format parameter by type

问题

以下是翻译好的部分:

这个lambda函数应该在编译时返回类似printf等的字符串格式化器,但似乎无法按预期工作,我无法理解它的工作原理。

当前输出:

  1. %llu

预期结果:

  1. %hhu

演示链接

  1. #include <array>
  2. #include <string_view>
  3. #include <iostream>
  4. int main() {
  5. using T = unsigned char;
  6. constexpr std::string_view fmt = [&]() -> std::string_view {
  7. std::tuple<char, unsigned char, short, unsigned short, int,
  8. unsigned int, long, unsigned long, long long, unsigned long long> dummy;
  9. constexpr std::size_t map_size = std::tuple_size_v<decltype(dummy)>;
  10. constexpr std::size_t idx = [&](auto... Is)(std::index_sequence<Is...>){
  11. std::size_t ret = 0;
  12. ([&]{ ret = Is; return std::same_as<T, decltype(std::get<Is>(dummy))>(); }() || ...);
  13. return ret;
  14. }(std::make_index_sequence<map_size>{});
  15. return std::array<std::string_view, map_size>{"%hhd", "%hhu", "%hd", "%hu", "%d", "%u", "%ld", "%lu", "%lld", "%llu"}[idx];
  16. }();
  17. std::cout << fmt << std::endl;
  18. }
英文:

The following lambda is supposed to return the string formatter for printf and alike at compiletime, however it doesn't seem to work as intended and I can't get behind it.

Demo

  1. #include &lt;array&gt;
  2. #include &lt;string_view&gt;
  3. #include &lt;iostream&gt;
  4. int main() {
  5. using T = unsigned char;
  6. constexpr std::string_view fmt = [&amp;]() -&gt; std::string_view {
  7. std::tuple&lt;char, unsigned char, short, unsigned short, int,
  8. unsigned int, long, unsigned long, long long, unsigned long long&gt; dummy;
  9. constexpr std::size_t map_size = std::tuple_size_v&lt;decltype(dummy)&gt;;
  10. constexpr std::size_t idx = [&amp;]&lt;std::size_t... Is&gt;(std::index_sequence&lt;Is...&gt;){
  11. std::size_t ret = 0;
  12. ([&amp;]{ ret = Is; return std::same_as&lt;T, decltype(std::get&lt;Is&gt;(dummy))&gt;; }() || ...);
  13. return ret;
  14. }(std::make_index_sequence&lt;map_size&gt;{});
  15. return std::array&lt;std::string_view, map_size&gt;{ &quot;%hhd&quot;, &quot;%hhu&quot;, &quot;%hd&quot;, &quot;%hu&quot;, &quot;%d&quot;, &quot;%u&quot;, &quot;%ld&quot;, &quot;%lu&quot;, &quot;%lld&quot;, &quot;%llu&quot; }[idx];
  16. }();
  17. std::cout &lt;&lt; fmt &lt;&lt; std::endl;
  18. }

Currently it outputs:

  1. %llu

Expected result:

  1. %hhu

答案1

得分: 4

decltype(std::get&lt;Is&gt;(dummy)) 在可变的 std::tuple 中为 T&amp;,在不可变的 std::tuple 中为 const T&amp;。请使用 std::tuple_element_t 替代:

  1. ([&amp;]{ ret = Is; return std::same_as&lt;T, std::tuple_element_t&lt;Is, decltype(dummy)&gt;&gt;; }() || ...);
英文:

decltype(std::get&lt;Is&gt;(dummy)) is T&amp; for a mutable std::tuple, const T&amp; for immutable std::tuple. Use std::tuple_element_t instead:

  1. ([&amp;]{ ret = Is; return std::same_as&lt;T, std::tuple_element_t&lt;Is, decltype(dummy)&gt;&gt;; }() || ...);

huangapple
  • 本文由 发表于 2023年6月29日 15:47:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579016.html
匿名

发表评论

匿名网友

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

确定