簡體   English   中英

基於仿函數參數計數類型的C ++重載

[英]C++ overloading by functor param count type

我正在為C ++ 11開發“LINQ to Objects”庫。 我想像這樣做:

// 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( ... ) - 這很難看。 所以我需要lambda類型的函數/方法重載...

這是我的解決方案:

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解決方案嗎? 你有什么建議我的?

也許是可變的東西:

#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作為返回類型,它執行相同的操作。

您當然希望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以獲得我們想要的行為。 這是一個謹慎的平衡行為,因為您不希望測試過於具體; 否則我們會失去普遍性。 編寫通用代碼時非常遺憾。 你沒有給出太多的信息(例如你是否對lambdas?單態函子?多態函子?)有嚴格的興趣,但我現在假設我們可以訪問一個value_type別名,它對應於你的例子中的double

因此,這是一個示例條件,它將使用簽名bool(value_type)檢查給定類型是否可調用(這是標准概念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> trait,所以我只需要template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>;寫一些類似template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>; (同樣我可以有一個is_binary_predicate別名,而不是讓my_magic_func的第二次重載成為一個全能的)。 也許你想在SFINAE的未來使用中使用類似的特性(盡管在沒有可變參數模板的情況下編寫可能有點痛苦)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM