Variadic模板选择更常见的模板而不是重载

时间:2017-03-02 14:19:27

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

想象一下这段代码:

#include <iostream>
void PrintInternal() {
    std::cout << std::endl;
}

template <typename T, typename...ARGS>
void PrintInternal(const T& head, const ARGS&...rest) {
    std::cout << head << " ";
    PrintInternal(rest...);
};

template <typename...ARGS>
void PrintInternal(const double& head, const ARGS&...rest) {
    std::cout << "DBL!!! " << head << " ";
    PrintInternal(rest...);
}

template <typename...ARGS>
void Print(const ARGS&...args) {
    PrintInternal(args...);
}

int main() {
    Print(1.1, 2, 3.3, 4);
    Print(0, 1.1, 2, 3.3, 4);
    return 0;
}

首先Print输出:

  

DBL !!! 1.1 2 3.3 4

我的期望是,它会输出DBL !!! 3.3之前或没有DBL !!!一点都不但为什么一个???

第二个Print输出:

  

0 1.1 2 3.3 4

为什么没有DBL !!!如果我们在第一个例子中有一个输出就像输出一样。

如何实现,对于每个double,我会输出一些不同而没有部分特化的东西?我想过,简单的重载应该没问题......

链接到cpp.sh以查看编译结果 - &gt; http://cpp.sh/42cz

2 个答案:

答案 0 :(得分:6)

查找PrintInternal()将找到两种类型的函数:

  • 在功能模板定义时可见的所有功能。
  • 函数模板的从属参数的关联命名空间中的所有函数。

在这种情况下,我们的所有参数都是基本类型,因此没有任何关联的命名空间。这使事情变得更容易。所以当我们开始时:

#include <iostream>
void PrintInternal() { // #1
    std::cout << std::endl;
}

template <typename T, typename...ARGS>
void PrintInternal(const T& head, const ARGS&...rest) { // #2
    std::cout << head << " ";
    PrintInternal(rest...); // <== (*)
};

template <typename...ARGS>
void PrintInternal(const double& head, const ARGS&...rest) { // #3
    std::cout << "DBL!!! " << head << " ";
    PrintInternal(rest...);
}

PrintInteral()的标记呼叫只有两个候选:nullary函数(#1)和它自己(#2)。另一个,PrintInteral()(#3)更加专业化const double&尚不可见,所以从未被视为候选人。并不是#2比#3更受欢迎,只是它是唯一的选择。

如果你翻转两个重载的顺序,那么你有一个不同的问题 - 你将无法找到#2!

这为您提供了一些选择:

  1. 单独打印单个元素以打印所有元素。这样,您只需要重载PrintSingle(),这样更容易。
  2. 转发声明所有功能模板,以便它们全部可见。
  3. 仅针对最重要的第二个要点引入另一个论点。只是一个伪参数,只是用ADL进行名称查找。这个解决方案有时是必要的,但总是令人困惑:

    namespace N {
        struct adl { };
    
        void PrintInternal(adl ) {
            std::cout << std::endl;
        }
    
        template <typename T, typename...ARGS>
        void PrintInternal(adl, const T& head, const ARGS&...rest) {
            std::cout << head << " ";
            PrintInternal(adl{}, rest...);
        }
    
        template <typename...ARGS>
        void PrintInternal(adl, const double& head, const ARGS&...rest) {
            std::cout << "DBL!!! " << head << " ";
            PrintInternal(adl{}, rest...);
        }
    }
    
    template <typename...ARGS>
    void Print(const ARGS&...args) {
        PrintInternal(N::adl{}, args...);
    }
    

答案 1 :(得分:0)

您有可见性问题,可以通过前瞻性声明来解决:

  $(window).load(function(){
      var resizeHero = function(){     
      var hero = $("#hero-fold")
      window1 = $(window);

      hero.css({
        "width": window1.width(),
        "height": "auto"
      });

    if(window1.width() < window1.height())
     {
         hero.css({
        "width": window1.width(),
        });

     }
   };

   resizeHero();

   $(window).resize(function(){
   resizeHero();    
     });
   });

Demo

更简单的方法是仅针对简单的打印,并将递归分开,例如:

template <typename...ARGS> void PrintInternal(const double& head, const ARGS&...rest);

template <typename T, typename...ARGS>
void PrintInternal(const T& head, const ARGS&...rest) {
    std::cout << head << " ";
    PrintInternal(rest...);
}

template <typename...ARGS>
void PrintInternal(const double& head, const ARGS&...rest) {
    std::cout << "DBL!!! " << head << " ";
    PrintInternal(rest...);
}

Demo