具有相同大小的两个可变参数模板参数

时间:2018-11-25 16:38:16

标签: c++ c++11 templates variadic-templates

我想实现一个打印功能,该功能可以做到这一点:

Data(contentsOf:url)

,我希望它将打印“ Hello”一次,“ World” 3次。我想知道如何实现它。 下面是我的愚蠢代码,当然编译时失败了:

URLSession.shared.dataTask

4 个答案:

答案 0 :(得分:3)

这将使它成为

template <unsigned int n, typename T>
void Print(T&& t)
{
    for(int i = 0; i < n; i++)
    {
        std::cout << std::forward<T>(t) << " ";
    }
    std::cout << std::endl;
}

template <std::size_t Idx1, std::size_t... Idx, class T, class... Ts>
void Print(T&& t, Ts&& ... ts) {
    Print<Idx1>(std::forward<T>(t));

    using expand = int[];
    (void)expand{(Print<Idx>(std::forward<Ts>(ts)), 0) ...};
}

答案 1 :(得分:1)

我还提出了一种完全不同的解决方案,完全避免了递归和for()循环。

它在初始化未使用的C样式数组时模拟C ++ 14中的模板折叠。

首先是主要的Print(),它扩展了调用Print_h()辅助函数的可变参数列表,向其传递了与每个值的迭代次数相对应的值和列表(索引序列)

template <std::size_t ... Ns, typename ... Ts>
void Print (Ts ... ts)
 {
   using unused=int[];

   (void)unused { 0, (Print_h(std::make_index_sequence<Ns>{}, ts), 0)... };
 }

下一步,使用相同技巧进行多次打印的帮助程序功能

template <std::size_t ... Is, typename T>
void Print_h (std::index_sequence<Is...>, T const & t)
 {
   using unused=std::size_t[];

   (void)unused { 0, (std::cout << t << " ", Is)... };

   std::cout << std::endl;
 }

以下是完整的C ++ 14示例

#include <utility>
#include <iostream>

template <std::size_t ... Is, typename T>
void Print_h (std::index_sequence<Is...>, T const & t)
 {
   using unused=std::size_t[];

   (void)unused { 0, (std::cout << t << " ", Is)... };

   std::cout << std::endl;
 }

template <std::size_t ... Ns, typename ... Ts>
void Print (Ts ... ts)
 {
   using unused=int[];

   (void)unused { 0, (Print_h(std::make_index_sequence<Ns>{}, ts), 0)... };
 }

int main ()
 {
   Print<1u, 3u>("hello", "world");
 }

如果您不能使用C ++ 14,而只能使用C ++ 11,那么开发std::make_index_sequencestd::index_sequence(只能从C ++ 14获得)的替代品并不难。

很明显,在C ++ 17中,您可以使用模板折叠来简化功能,如下所示

template <std::size_t ... Is, typename T>
void Print_h (std::index_sequence<Is...>, T const & t)
 {    
   ((std::cout << t << " ", (void)Is), ...);

   std::cout << std::endl;
 }

template <std::size_t ... Ns, typename ... Ts>
void Print (Ts ... ts)
 { (Print_h(std::make_index_sequence<Ns>{}, ts), ...); }

答案 2 :(得分:0)

您可以通过交换两个重载的声明并在递归调用中删除ts...模板参数来使代码工作:

template <unsigned int n, typename T>
void Print(T & t)
{
    for(unsigned int i = 0; i < n; i++)
    {
        std::cout << t << " ";
    }
    std::cout << std::endl;
}

template <unsigned int n, unsigned int ...n_next,
          typename T, typename ...Ts>
void Print(T & t, Ts & ... ts)
{
    for(unsigned int i = 0; i < n; i++)
    {
        std::cout << t << " ";
    }
    std::cout << std::endl;

    Print<n_next...>(ts...);
}

(也要与签名保持一致)
Demo

此外,您无需复制打印部分,只需调用另一个重载即可:

template <unsigned int n, typename T>
void Print(T & t)
{
    for(unsigned int i = 0; i < n; i++)
    {
        std::cout << t << " ";
    }
    std::cout << std::endl;
}

template <unsigned int n, unsigned int ...n_next,
          typename T, typename ...Ts>
void Print(T & t, Ts & ... ts)
{
    Print<n>(t);
    Print<n_next...>(ts...);
}

或者,如果可以将C ++ 17用于折叠表达式,则可以执行以下操作(如果需要,可以使用转发引用和std::forward):

template<typename T>
void Print(unsigned int n, T& t)
{
    for(unsigned int i = 0; i < n; i++)
    {
        std::cout << t << " ";
    }
    std::cout << std::endl;
}

template<unsigned int... Ns, typename... Ts>
void Print(Ts&... ts)
{
    (Print(Ns, ts), ...);
}

Demo

答案 3 :(得分:0)

我在您的代码中看到了四个问题

(1)递归调用

30 // 2

是错误的,因为您必须在模板参数列表中使用type (30//2)类型,而不是Print<n_next..., ts...>(ts...);

Ts...

或者更好(因为我将在下面解释一个技巧)而无需说明类型

ts...
如果 const 引用值

,则

(2)更好

Print<n_next..., Ts...>(ts...);

否则,您不能使用以下常量值调用Print<n_next...>(ts...);

template <unsigned int n, unsigned int ...n_next,
          typename T, typename ...Ts>
void Print(T const & t, Ts ... ts)
// ..........^^^^^

(3)最好对Print()循环中的索引使用无符号值,因为您必须使用无符号值测试它们(次要问题)

Print<1u, 3u>(1, "world");

(4)您必须在递归案例之前放置for(仅接收值的案例)的基础案例。

我建议用

代替它们
// ..VVVVVVVV
for (unsigned int i = 0; i < n; i++)

因为这样,所有打印都是在递归版本中完成的,因此您不必在两个不同的函数中重复相同的代码(但您必须调用Print()递归。

所以我建议如下修改您的代码

template <typename = void>
void Print ()
 { }
相关问题