Непревзойденный шаблон для простой переменной функции в C ?

#c #templates #c 14 #template-argument-deduction #transpiler

#c #шаблоны #c 14 #шаблон-аргумент-вывод #транспилировщик

Вопрос:

Я пишу схему для компилятора C (хотя схема не имеет такого отношения к этому вопросу), и у меня есть набор функций, которые вызываются в коде 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 amp;amp; ./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.
  

Ответ №1:

Аргументы шаблона могут быть выведены только из аргументов функции. В этом случае первый параметр шаблона T из f не может быть выведен, он используется только для указания типа возвращаемого значения функции.

Когда это возможно, компилятор выведет отсутствующие аргументы шаблона из аргументов функции.

Вы должны явно указать аргумент, например

 display(f<int>(1, 2, 3));
//       ^^^^^
  

Или вы можете удалить параметр шаблона из f (и позволить вывести возвращаемый тип):

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

Комментарии:

1. Проблема в том, что, поскольку я генерирую этот код из кода Scheme, в коде Scheme нет указания типа переменной, поэтому я не могу последовательно вывести тип. Знаете ли вы другой способ решить мою проблему — т. Е. создать универсальную функцию, которая принимает универсально типизированные аргументы с универсальным выводом, где мне не нужно указывать тип вывода?

2. @CaspianAhlberg Не могли бы вы изменить f объявление? Исправленный ответ.