Я пытаюсь специализировать шаблонную функцию на основе арма лямбды, которую я передаю ей в качестве аргумента.Вот что я придумала для решения:
template<typename Function, bool>
struct helper;
template<typename Function>
struct helper<Function, false>
{
auto operator()(Function&& func)
{
std::cout << "Called 2 argument version.\n";
return func(1, 2);
}
};
template<typename Function>
struct helper<Function, true>
{
auto operator()(Function&& func)
{
std::cout << "Called 3 argument version.\n";
return func(1, 2, 3);
}
};
template<typename T>
struct B
{
T a;
const T someVal() const { return a; }
};
template<typename Function, typename T>
auto higherOrderFun(Function&& func, const T& a)
{
return helper<Function, std::is_invocable<Function, decltype(a.someVal()), decltype(a.someVal()), decltype(a.someVal())>::value>{}(std::forward<Function>(func));
}
int main()
{
B<int> b;
std::cout << higherOrderFun([](auto x, auto y) {return x+y; }, b) << "\n";
std::cout << higherOrderFun([](auto x, auto y, auto z) {return x + y+z; }, b) << "\n";
return 0;
}
Есть ли способ добиться этого более элегантным способом?Я просмотрел это: Arity универсальной лямбды
Однако последнее решение (florestan's) превращает все аргументы в aribtrary_t
, поэтому их нужно отбрасывать обратно внутрь каждоголямбда, которую я не нахожу идеальной.В идеале мне хотелось бы напрямую специализировать шаблон higherOrderFun
с SFINAE, но для этого я использую вспомогательный класс.Есть ли более прямой путь?Например, применить SFINAE непосредственно к higherOrderFun
, не полагаясь на класс helper
?Весь смысл в том, что не нужно менять higherOrderFun
на higherOrderFun2
и higherOrderFun3
, а нужно, чтобы компилятор выводил правильную специализацию из лямбды и заданного аргумента (const T& a
).
Я должен отметить, что меня также не волнует тип аргументов функции - только их количество, поэтому я бы изменил decltype(a.someVal())
на auto
в моем примере, если бы это было возможно(может быть, есть способ обойти явное определение типов?).