#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
объявление? Исправленный ответ.