`参数包递归扩展时没有匹配的call`函数

时间:2016-09-12 15:11:45

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

请考虑以下计划:

#include <iostream>


template <int I, typename T, typename ...Args>
struct foo {
    static void bar(const T& t0, const T& t1, const Args&... args)
    {
        std::cout << "( " << t0 << ", " << t1 << " ) ";
        foo::bar(args...);
    }
};

template <int I, typename T>
struct foo<I, T> {
    static void bar(const T& t0, const T& t1)
    {
        std::cout << "( "<< t0 << ", " << t1 << " ) " << std::endl;
    }
};


int main() {
    foo<1, int, float>::bar(0, 1, 18.f, -7.f);
    return 0;
}

我希望它能正常编译并在运行时输出以下内容(

( 0, 1 ) ( 18, -7 )

但是,此代码通过g++ -std=c++14 -pedantic -Wall -Wextra parampack.cpp(GCC 5.3.0)生成以下输出:

parampack.cpp: In function ‘int main()’:
parampack.cpp:23:45: error: no matching function for call to ‘foo<1, int, float>::bar(int, int, float, float)’
     foo<1, int, float>::bar(0, 1, 18.f, -7.f);
                                             ^
parampack.cpp:6:17: note: candidate: static void foo<I, T, Args>::bar(const T&, const T&, const Args& ...) [with int I = 1; T = int; Args = {float}]
     static void bar(const T& t0, const T& t1, const Args&... args)
                 ^
parampack.cpp:6:17: note:   candidate expects 3 arguments, 4 provided
parampack.cpp: In instantiation of ‘static void foo<I, T, Args>::bar(const T&, const T&, const Args& ...) [with int I = 1; T = int; Args = {float}]’:
parampack.cpp:23:25:   required from here
parampack.cpp:9:17: error: no matching function for call to ‘foo<1, int, float>::bar(const float&)’
         foo::bar(args...);
                 ^
parampack.cpp:6:17: note: candidate: static void foo<I, T, Args>::bar(const T&, const T&, const Args& ...) [with int I = 1; T = int; Args = {float}]
     static void bar(const T& t0, const T& t1, const Args&... args)
                 ^
parampack.cpp:6:17: note:   candidate expects 3 arguments, 1 provided

我尝试了各种变体和排列,例如:

template <int I, typename T, typename U, typename ...Args>
struct foo {
    static void bar(const T& t0, const T& t1, const U& u0, const U& u1, const Args&... args)
    {
        std::cout << "( " << t0 << ", " << t1 << " ) ";
        foo::bar(u0, u1, args...);
    }
};

...但我似乎无法编译而且我不确定究竟发生了什么

为什么编译器没有找出要实例化的函数?

1 个答案:

答案 0 :(得分:4)

首先,你有错误的参数数量 - 正如编译器建议的那样。 foo<1, int float>::bar()有签名:

static void bar(int const&, int const&, float const& );

这3个论点。你正在传入4.因此直截了当的错误。

你显然要做的是一次挑选2个参数。在这种情况下,bar中的尾随参数与foo中的尾随参数不同,因此您需要:

template <int I, typename T, typename ...Args>
struct foo {
    template <class... Extra>
    static void bar(const T& t0, const T& t1, const Extra&... args)
    {
        std::cout << "( " << t0 << ", " << t1 << " ) ";
        foo::bar(args...); // <== (*)
    }
};

这将带来第二个问题:对foo::bar()的递归调用。 foo有主模板的注入类名。这将永远不会让你进入你的基础案例专业化。那么,你想要:

foo<I, Args...>::bar(args...);