【问题标题】:Expansion of a variadic template function causes segmentation fault可变参数模板函数的扩展导致分段错误
【发布时间】:2013-05-22 13:10:31
【问题描述】:

我正在研究C++11关于Variadic Templates的新特性,所以写了一个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。谁能向我解释为什么会发生这种情况?

【问题讨论】:

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


    【解决方案1】:

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

    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...);
    }
    

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

    【讨论】:

    • 在第二个有趣的定义中只有fun(rest...);fun(first); fun(rest...); 有什么区别?我在一些例子中看到了第二个。
    • fun(first) 会寻找一个 fun 版本,它接受一个参数并调用它。好有趣(第一);乐趣(休息...);会在第一个参数上调用 fun,然后在其余参数上递归调用 fun。您需要确保以这种方式调用您的函数是有意义的。
    猜你喜欢
    • 2014-04-12
    • 1970-01-01
    • 2014-10-30
    • 2013-10-03
    • 2013-08-04
    • 2021-04-19
    • 2015-05-21
    • 1970-01-01
    相关资源
    最近更新 更多