C ++通过算符PARAM计数类型超载(C++ overloading by functor par

2019-07-29 08:58发布

我的工作“LINQ到对象”库,用于C ++ 11。 我想这样做水木清华这样的:

// filtering elements by their value
arr.where( [](double d){ return d < 0; } )

// filtering elements by their value and position
arr.where( [](double d, int i){ return i%2==0; } )

我倒想写arr.where_i( ... ) -它是丑陋的。 所以我需要通过拉姆达型函数/方法重载...

这是我的解决方案:

template<typename F>
auto my_magic_func(F f) -> decltype(f(1))
{
    return f(1);
}

template<typename F>
auto my_magic_func(F f, void * fake = NULL) -> decltype(f(2,3))
{
    return f(2,3);
}

int main()
{
    auto x1 = my_magic_func([](int a){ return a+100; });
    auto x2 = my_magic_func([](int a, int b){ return a*b; });
    // x1 == 1+100
    // x2 == 2*3
}

它是SFINAE解决方案吗? 你能建议我?

Answer 1:

也许一些可变参数:

#include <utility>

template <typename F, typename ...Args>
decltype(f(std::declval<Args>()...) my_magic_func(F f, Args &&... args)
{
    return f(std::forward<Args>(args)...);
}

编辑:您还可以使用typename std::result_of<F(Args...)>::type的返回类型,它做同样的事情。



Answer 2:

你一定要SFINAE在您的解决方案。 一般来说,结果看起来是这样的:

template<
    typename Functor
    , typename std::enable_if<
        special_test<Functor>::value
        , int
    >::type = 0
>
return_type
my_magic_func(Functor f);

template<
    typename Functor
    , typename std::enable_if<
        !special_test<Functor>::value
        , int
    >::type = 0
>
return_type
my_magic_func(Functor f);

这样,只有一个过载会活跃在任何一个时间-这一切仍然正在认真起草该special_test有我们想要的行为。 这是因为你不想测试太具体了仔细的平衡; 否则就失去普遍性。 编写通用代码时,真丢人。 您还没有给出太多的信息(例如你在支持严格兴趣的lambda表达式?单形仿函数?多态性函子?),但我会承担,现在我们有机会获得一个value_type别名,这将相当于double在你的榜样。

因此,这里的一个例子条件,将检查给定的类型是可调用(这是一个标准的概念)与签名bool(value_type) ; 也就是说,它是某种形式的谓语:

template<typename Functor, typename ValueType>
struct is_unary_predicate {
    typedef char (&accepted)[1];
    typedef char (&refused)[2];

    void consume(bool);

    template<
        typename X
        , typename Y
        , typename = decltype( consume(std::declval<X>()(std::declval<Y>())) )
    >
    accepted
    test(X&&, Y&&);

    refused test(...);

    static constexpr bool value =
        sizeof test(std::declval<Functor>(), std::declval<ValueType>())
        == sizeof(accepted);
};

我个人有一个is_callable<F, Signature>性状,这样我只需要编写类似template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>; (类似地,我可以有一个is_binary_predicate而不是让的第二过载别名my_magic_func是捕获所有)。 也许你会想使用SFINAE的未来使用类似的特征(虽然它可能会有些痛苦,而不可变参数模板写)。



文章来源: C++ overloading by functor param count type