(C++11) 可变参数模板序列打印

Posted

技术标签:

【中文标题】(C++11) 可变参数模板序列打印【英文标题】:(C++11) Variadic template sequence printing 【发布时间】:2020-11-18 18:59:37 【问题描述】:

我遇到了一个模板元编程挑战,即仅使用 C++11 标准打印出一系列 2 的幂的整数,我已经成功完成了:

#include <iostream>

template <size_t... Ns>
struct index_sequence

    static void print()
    
        const size_t numbers[] = Ns...;
        for (const auto& number : numbers)
        
            std::cout << number << ", ";
        
        std::cout << std::endl;
    
;

//#include <cmath>

template <size_t Counter, size_t... Rest>
struct make_sequence_impl

    using type = typename make_sequence_impl<
        Counter - 1,
        static_cast<size_t>(1) << Counter, Rest...>::type;
;

template <size_t... Rest>
struct make_sequence_impl<0, Rest...>

    using type = index_sequence<static_cast<size_t>(1) << 0, Rest...>;
;

template <size_t T>
using make_sequence = typename make_sequence_impl<T>::type;

int main()

    make_sequence<N>::print();

假设 N 为 5,它将打印 1、2、4、8、16。

然而,我随后被要求做同样的事情,只是这次我必须以相反的顺序打印它们(即 N = 5 时,16、8、4、2、1)。我完全被难住了,但我很确定它只涉及对代码的轻微更改,我不知道如何。

任何帮助将不胜感激。几天前开始接触模板元编程。

【问题讨论】:

在循环中使用reverse_iterator 我会模仿std::make_integer_sequence 拥有sequence&lt;Is...&gt;,然后使用转换方法拥有sequence&lt;(1 &lt;&lt; Is)...&gt;sequence&lt;(1 &lt;&lt; (sizeof...(Is) - 1 -Is))...&gt; 【参考方案1】:

不确定这是否是最小的变化,但您可能 "push_front" 而不是序列,而是 "push_back"

template <size_t Counter, size_t... Rest>
struct make_sequence_impl

    using type = typename make_sequence_impl<
        Counter - 1,
        Rest...,
        static_cast<size_t>(1) << Counter>::type;
;

template <size_t... Rest>
struct make_sequence_impl<0, Rest...>

    using type = index_sequence<Rest..., static_cast<size_t>(1) << 0>;
;

Demo

在我这边,我会模仿std::make_index_sequence 拥有0, 1, 2, .., N-1,然后直接使用它:

emplate <size_t Counter, size_t... Rest>
struct make_sequence_impl

    using type = typename make_sequence_impl<
        Counter - 1,
        Counter,
        Rest...>::type;
;

template <size_t... Rest>
struct make_sequence_impl<0, Rest...>

    using type = index_sequence<0, Rest...>;
;

然后

template <std::size_t ... Is>
void print( index_sequence<Is...> )

    for (const auto& number : Is...)
    
        std::cout << number << ", ";
    
    std::cout << std::endl;



template <std::size_t ... Is>
void print_pow2( index_sequence<Is...> )

    print(index_sequence<(1u << Is)...>);


template <std::size_t ... Is>
void print_pow2_inv( index_sequence<Is...> )

    print(index_sequence<(1u << (sizeof...(Is) - 1 - Is))...>);

Demo

【讨论】:

天哪……我怎么没想到呢?我一直认为你不能“push_front”一个模板化的参数包序列,而我正接近探索实现一个反向解包的函数的地步。非常感谢!我希望我能在这方面做得更好...... 关于“push_front”实现和“minic make_index_sequence”实现的另一个问题。我都试过了,他们都表现得像预期的那样。两者之间是否存在任何实际差异,或者后者只是您会做的一种实现? 可能首先是命名问题,因为您的make_sequencestd::make_sequence 不匹配,make_sequnce_pow 本来会更好的命名。然后一旦完成一个序列,就更容易操作它,每次我们需要它时重新创建另一个。

以上是关于(C++11) 可变参数模板序列打印的主要内容,如果未能解决你的问题,请参考以下文章

C++11 ——— 可变参数模板

C++11 ——— 可变参数模板

[C++11 模板的改进] --- 可变参数模板

C++11:可变参数模板函数参数的数量?

print使用可变参数宏对调试行进行多次打印

C++11 可变参数模板