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