请考虑以下计划:
#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...);
}
};
...但我似乎无法编译而且我不确定究竟发生了什么。
为什么编译器没有找出要实例化的函数?
答案 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...);