通过类型检索printf格式参数

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

Retrieving printf format parameter by type

问题

以下是翻译好的部分:

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

当前输出:

%llu

预期结果:

%hhu

演示链接

#include <array>
#include <string_view>
#include <iostream>

int main() {
    using T = unsigned char;
    constexpr std::string_view fmt = [&]() -> std::string_view {
        std::tuple<char, unsigned char, short, unsigned short, int,
            unsigned int, long, unsigned long, long long, unsigned long long> dummy;
        constexpr std::size_t map_size = std::tuple_size_v<decltype(dummy)>;
        constexpr std::size_t idx = [&](auto... Is)(std::index_sequence<Is...>){
            std::size_t ret = 0;
            ([&]{ ret = Is; return std::same_as<T, decltype(std::get<Is>(dummy))>(); }() || ...);
            return ret;
        }(std::make_index_sequence<map_size>{});
        return std::array<std::string_view, map_size>{"%hhd", "%hhu", "%hd", "%hu", "%d", "%u", "%ld", "%lu", "%lld", "%llu"}[idx];
    }();
    std::cout << fmt << std::endl;
}
英文:

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

#include &lt;array&gt;
#include &lt;string_view&gt;
#include &lt;iostream&gt;

int main() {
    using T = unsigned char;
    constexpr std::string_view fmt = [&amp;]() -&gt; std::string_view {
        std::tuple&lt;char, unsigned char, short, unsigned short, int,
            unsigned int, long, unsigned long, long long, unsigned long long&gt; dummy;
        constexpr std::size_t map_size = std::tuple_size_v&lt;decltype(dummy)&gt;;
        constexpr std::size_t idx = [&amp;]&lt;std::size_t... Is&gt;(std::index_sequence&lt;Is...&gt;){
            std::size_t ret = 0;
            ([&amp;]{ ret = Is; return std::same_as&lt;T, decltype(std::get&lt;Is&gt;(dummy))&gt;; }() || ...);
            return ret;
        }(std::make_index_sequence&lt;map_size&gt;{});
        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];
    }();
    std::cout &lt;&lt; fmt &lt;&lt; std::endl;
}

Currently it outputs:

%llu

Expected result:

%hhu

答案1

得分: 4

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

            ([&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:

            ([&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:

确定