C++ 中简单可变参数函数的无与伦比的模板?
Unmatched template for simple variadic function in C++?
我正在为 C++ 编译器编写一个 Scheme(尽管 Scheme 与这个问题没有太大关系),并且我有一组在 Scheme 代码中调用的函数,这些函数可以在生成的 C++ 代码中等效地使用。我生成了 C++ 函数“f”(见下文),但我终究无法弄清楚为什么它不起作用(错误如下)。我有三个模板化参数,我也为函数提供了三个参数。如果您对这个问题有任何见解,请告诉我 - 这太令人沮丧了!
// from stdarg_macros.h
#include <stdarg.h>
#define INIT va_list args; va_start(args, nargs);
#define LOOP for (int i = 0; i < nargs; i++)
#define DEINIT va_end(args); return r;
// from io.cpp
#include <iostream>
template <typename T>
void display(T var) {
std::cout << var << std::endl;
}
// from operators.c
int add(int nargs, ...) {INIT int r = 0; LOOP r += va_arg(args, int); DEINIT}
double add_d(int nargs, ...) { INIT double r = 0; LOOP r += va_arg(args, double); DEINIT}
int sub(int nargs, ...) {INIT int r; LOOP {if (i == 0) r = va_arg(args, int); else r -= va_arg(args, int);} DEINIT}
double sub_d(int nargs, ...) {INIT int r; LOOP {if (i == 0) r = va_arg(args, double); else r *= va_arg(args, double);} DEINIT}
int mul(int nargs, ...) {INIT int r = 1; LOOP r *= va_arg(args, int); DEINIT}
double mul_d(int nargs, ...) {INIT double r = 1; LOOP r *= va_arg(args, double); DEINIT}
double div_d(int nargs, ...) {INIT double r; LOOP {if (i == 0) r = va_arg(args, double); else r /= va_arg(args, double);} DEINIT}
// my transpiler's output file
template <typename T, typename S, typename M, typename x>
T f(S a, M b, x c) {
return mul_d(3, a, b, div_d(2, 3.0, c));
};
int main() {
auto m = mul_d(3, 8.0, 2.0, div_d(2, 5.0, 3.0));
display(m);
display(f(1, 2, 3));
return 0;
}
$ g++ -std=c++14 Output/math.cpp && ./a.out
Output/math.cpp:9:9: error: no matching function for call to 'f'
display(f(1, 2, 3));
^
Output/math.cpp:3:3: note: candidate template ignored: couldn't infer template argument 'T'
T f(g a, i b, L c) {
^
1 error generated.
模板参数只能从函数参数推导出来。在这种情况下,f
的第一个模板参数T
不能是deduced,它只用于指定函数的return类型。
When possible, the compiler will deduce the missing template arguments from the function arguments.
你必须像
一样明确指定参数
display(f<int>(1, 2, 3));
// ^^^^^
或者您可以从 f
中删除模板参数(并推导 return 类型):
template <typename S, typename M, typename x>
auto f(S a, M b, x c) {
return mul_d(3, a, b, div_d(2, 3.0, c));
};
那你就可以这样称呼它了
display(f(1, 2, 3));
我正在为 C++ 编译器编写一个 Scheme(尽管 Scheme 与这个问题没有太大关系),并且我有一组在 Scheme 代码中调用的函数,这些函数可以在生成的 C++ 代码中等效地使用。我生成了 C++ 函数“f”(见下文),但我终究无法弄清楚为什么它不起作用(错误如下)。我有三个模板化参数,我也为函数提供了三个参数。如果您对这个问题有任何见解,请告诉我 - 这太令人沮丧了!
// from stdarg_macros.h
#include <stdarg.h>
#define INIT va_list args; va_start(args, nargs);
#define LOOP for (int i = 0; i < nargs; i++)
#define DEINIT va_end(args); return r;
// from io.cpp
#include <iostream>
template <typename T>
void display(T var) {
std::cout << var << std::endl;
}
// from operators.c
int add(int nargs, ...) {INIT int r = 0; LOOP r += va_arg(args, int); DEINIT}
double add_d(int nargs, ...) { INIT double r = 0; LOOP r += va_arg(args, double); DEINIT}
int sub(int nargs, ...) {INIT int r; LOOP {if (i == 0) r = va_arg(args, int); else r -= va_arg(args, int);} DEINIT}
double sub_d(int nargs, ...) {INIT int r; LOOP {if (i == 0) r = va_arg(args, double); else r *= va_arg(args, double);} DEINIT}
int mul(int nargs, ...) {INIT int r = 1; LOOP r *= va_arg(args, int); DEINIT}
double mul_d(int nargs, ...) {INIT double r = 1; LOOP r *= va_arg(args, double); DEINIT}
double div_d(int nargs, ...) {INIT double r; LOOP {if (i == 0) r = va_arg(args, double); else r /= va_arg(args, double);} DEINIT}
// my transpiler's output file
template <typename T, typename S, typename M, typename x>
T f(S a, M b, x c) {
return mul_d(3, a, b, div_d(2, 3.0, c));
};
int main() {
auto m = mul_d(3, 8.0, 2.0, div_d(2, 5.0, 3.0));
display(m);
display(f(1, 2, 3));
return 0;
}
$ g++ -std=c++14 Output/math.cpp && ./a.out
Output/math.cpp:9:9: error: no matching function for call to 'f'
display(f(1, 2, 3));
^
Output/math.cpp:3:3: note: candidate template ignored: couldn't infer template argument 'T'
T f(g a, i b, L c) {
^
1 error generated.
模板参数只能从函数参数推导出来。在这种情况下,f
的第一个模板参数T
不能是deduced,它只用于指定函数的return类型。
When possible, the compiler will deduce the missing template arguments from the function arguments.
你必须像
一样明确指定参数display(f<int>(1, 2, 3));
// ^^^^^
或者您可以从 f
中删除模板参数(并推导 return 类型):
template <typename S, typename M, typename x>
auto f(S a, M b, x c) {
return mul_d(3, a, b, div_d(2, 3.0, c));
};
那你就可以这样称呼它了
display(f(1, 2, 3));