3

我正在研究关于可变参数模板的新 C++11 功能,所以我写了一个fun模板函数:

template <typename T>
void fun(T& a) //Base to stop the recursion
{
  std::cout << a;
};

template <typename... Types>
void fun(Types... args)
{
  fun(args...);
};

模板编译得很好,但是当我写在我得到main 一个 . 谁能向我解释为什么会这样?fun(1,10.232,1232);Segmentation fault

4

1 回答 1

6

我不知道段错误,但你永远不会调用你的基本函数。您需要在每次调用后缩小参数列表:

template <typename T>
void fun(T& a) //Base to stop the recursion
{
    std::cout << a;
};

template <typename First, typename... Types>
void fun(First arg, Types... args)
{
    fun(args...); // recursion on args... (one smaller than what was passed in).
};

您的基本案例通过引用绑定,这不是一个好主意,因为您在调用站点传递临时对象。这可能是您的段错误的来源。通过 const 引用或按值将函数更改为接受。

另请注意,我没有编译上面的代码,因此当您只使用一个参数调用 fun 时,您最终可能会陷入模棱两可的情况。要解决此问题,请将您的基本情况更改为不接受任何参数:

void fun()
{
    // base case: no items.
}

template <typename First, typename... Rest>
void fun(First first, Rest... rest)
{
    // one or more items (the param pack is allowed to be emoty.)
    fun(rest...);
}

或修改递归重载以接受两个或更多参数。

// Exactly one argument.
template <typename T>
void fun(T a)
{
    std::cout << a;
};

// Two or more arguments.
template <typename First, typename Second, typename... Rest>
void fun(First first, Second second, Rest... rest)
{
    // one or more items (the param pack is allowed to be emoty.)
    fun(second, rest...);
}

无论哪种方式,都尽量避免出现多个函数模板作为扩展候选者的情况,这样您就可以避免很多麻烦。换句话说:每个重载都应该是互斥的。

于 2013-05-22T13:14:56.603 回答