У меня есть шаблон функции, который принимает функцию в качестве аргумента. Я хотел бы получить имя аргумента функции из шаблона. Ниже приведен полный пример. См. Строку с надписью «COMPILE ERROR». Я попытался выполнить множество подобных действий, но я продолжаю получать ту же ошибку, «функция throws.thrower (int n) не может быть вызвана».Как получить имя псевдонима функции в шаблоне D?
import std.array;
import std.conv;
import std.format;
import std.stdio;
int thrower(int n)
{
if(n > 5)
throw new core.exception.RangeError("too big");
return n * 2;
}
int thrower2(int x, int y)
{
int product = x * y;
if(product > 25)
throw new core.exception.RangeError("too big");
return product;
}
void assertThrows(alias fun, E, T...)(T t)
{
try
{
fun(t);
auto writer = appender!string();
formattedWrite(writer,
"Expected %s to throw %s, but it did not",
// throws.d(32): Error: function throws.thrower (int n) is not callable using argument types()
//fun.stringof, // <<-- COMPILE ERROR
"?",
E.stringof);
throw new core.exception.AssertError(writer.data);
}
catch(E ex)
{
// Success - we got the expected exception - do nothing.
}
// We don't catch any other exceptions -- if these occur they will
// cause a failure directly, or be handled by other test code that
// may be expecting the exception. Either way we don't want to
// interfere.
}
int main()
{
assert(thrower(5) == 10);
assertThrows!(thrower, core.exception.RangeError)(6);
assertThrows!(thrower2, core.exception.RangeError)(9, 9);
assertThrows!(thrower2, core.exception.RangeError)(1, 1); // Should fail
return 0;
}
Я хотел бы указать, что нет никакой гарантии, что 'fun' - это даже функция с именем. Это может быть функция лямбда или какой-либо другой вызываемый, который прошел. Кроме того, у нас есть 'std.exception.assertThrown', поэтому в стандартной библиотеке есть что-то, что делает то, что ваша функция пытается (хотя он использует файл и номер строки, а не имя функции в сообщении об ошибке). –
Спасибо за подсказку - 'fullQualifiedName' дает« main .__ funcliteral1 », когда я тестирую его с помощью лямбда, что кажется достаточно разумным. Файл и строка, вероятно, более полезны. Я очень новичок в D, поэтому полезен указатель на 'assertThrown' в стандартной библиотеке. Я искал его в неправильных местах и не понимал, что это было в этом модуле. По крайней мере, я изучил полдюжины новых вещей, изобретая это конкретное колесо :) – bstpierre
Если вам не нужно полное имя и убедитесь, что он действительный символ, '__traits (identifier, Symbol)' тоже будет делать трюк. –