Сначала определите обобщенную функцию, целью которой является выполнение функции для списка входов, и распечатайте каждый вход и соответствующий результат выполнения функции.
В дальнейшем func
является ссылкой нафункция, funcName
- это просто имя функции для отображения терминала, inputs
- аргументы для func
.
#define TBOLD(x) "\x1B[1m" x __RST
#define TRED(x) __KRED x __RST
template<typename ...TInputs, typename TOutput>
void test_func(TOutput func(TInputs &...),
const string &funcName,
vector<tuple<TInputs...>> inputs,
const string &resultDelimiter = ", ")
{
cout << funcName << endl;
if (is_same<TOutput, bool>::value)
cout << boolalpha;
for (auto &input: inputs)
{
auto arg_idx = 0;
apply([&arg_idx](auto &&... args)
{ ((std::cout << args << (++arg_idx == sizeof...(TInputs) ? TBOLD(TRED(" : ")) : ", ")), ...); }, input);
cout << apply(func, input) << endl;
}
}
Теперь предположим, что у меня есть следующие функции,
static int func1(vector<int> &arr, int &k)
{
sort(arr.begin(),arr.end());
return arr[k];
}
template<typename Container>
static typename Container::value_type func2(Container &arr, int &k)
{
sort(arr.begin(),arr.end());
return arr[k];
}
Теперь следующая строка будет скомпилирована,
test_func(func1,"func1",vector<tuple<vector<int>,int>>{make_tuple(vector<int>{3,5,1,2,4},2)})
, но следующая не скомпилирует и выдаст сообщение, что « не может вывести аргумент шаблона TOutput ».По моему мнению, это должно было предоставить достаточно информации для вывода типа вывода TOutput
: аргумент inputs
имеет тип vector<tuple<vector<int>,int>>
, тогда он должен знать, что TInputs...
равен <Container, int>
, а затем TOutput
равен Container::value_type
.
test_func(func2,"func2",vector<tuple<vector<int>,int>>{make_tuple(vector<int>{3,5,1,2,4},2)})
Если это действительно не работает, как правильно сделать тип возвращаемого значения правильно распознанным, сохраняя при этом «общность» этого test_func
для принятия функцийразные аргументы и вывод?