【发布时间】:2019-11-15 15:25:14
【问题描述】:
我正在尝试根据我作为参数传递给它的 lambda 的数量来专门化一个模板化函数。这是我想出的解决方案:
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 of a generic lambda
但是,最新的解决方案(florestan's)将所有参数转换为aribtrary_t,因此必须将它们转换回每个 lambda 内部,我认为这并不理想。理想情况下,我希望使用 SFINAE 直接专门化模板化的 higherOrderFun,但因为它是我使用辅助类来实现的。有没有更直接的方法?例如直接将 SFINAE 应用到 higherOrderFun 而不依赖于 helper 类?这样做的重点是不必将higherOrderFun 更改为higherOrderFun2 和higherOrderFun3,而是让编译器从lambda 和给定参数(const T& a)中推断出正确的特化。
我应该提到,我也不关心函数参数的类型 - 只关心它们的数量,所以如果可能的话,我会在我的示例中将 decltype(a.someVal()) 更改为 auto(也许有一种规避显式定义类型的方法?)。
【问题讨论】:
-
如果
func既可以接受两个参数又可以接受三个参数呢? -
"aribtrary_t,因此必须将它们转换回每个 lambda"。不,它仅在未评估的上下文中使用(因此,如果有,请不要实例化通用 lambda)。
-
@Jarod42 我尝试在 msvc2017 中将他的
arity_v用于 SFINAE,它需要在每个 lambda 中进行强制转换,因为当我使用arity_v时它显然是用arbitrary_t实例化了它。不过,当我回来时,我可以尝试创建一个最小的示例。 -
如何,确实它的特征并没有像我们预期的那样工作Demo。
-
@Jarod42 是的,这正是我的意思。谢谢你举个例子,我在原帖里已经提到了。
标签: c++ templates lambda c++17 arity