過濾

2013-08-17 32 views
2

我要「過濾器」就像在下面的代碼的可變參數模板函數的參數包(需要「過濾器」只有某些類型的變量):過濾

#include <iostream> 
#include <utility> 
#include <cstdlib> 

struct Z {}; 

struct test 
{ 

    using result_type = void; 

    template< typename... P > 
    result_type apply_filter(P &&... _p) const 
    { 
     using std::forward; 
     return operator() (forward<P>(_p)...); 
    } 

    template< typename... T > 
    result_type operator() (std::string const & _s, T &&... _tail) const 
    { 
     std::cout << _s << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

    template< typename... T > 
    result_type operator() (double const & _x, T &&... _tail) const 
    { 
     std::cout << _x << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

    template< typename... T > 
    result_type operator() (Z const &, T &&... _tail) const 
    { 
     std::cout << "z" << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

private : 

    result_type operator()() const { return; } 

    template< typename T, typename U > 
    using is_the_same = std::is_same< typename std::remove_const< typename std::remove_reference<T>::type >::type, U >; 

    template< typename T > 
    typename std::enable_if< is_the_same< T, std::string >::value, std::string >::type 
    forward(T && _s) const 
    { 
     return "\"" + _s + "\""; 
    } 

    template< typename T > 
    typename std::enable_if< is_the_same< T, double >::value, double >::type 
    forward(T && _x) const 
    { 
     return _x + 1.0; 
    } 

}; 

int main() 
{ 
    test test_; 
    double x = 0.0; 
    std::string s = "s"; 
    Z z; 
    test_.apply_filter(x, s, z); 
    return EXIT_SUCCESS; 
} 

但是std::forwardapply_filter中的成員函數具有更高的優先級。因此在這裏沒有發生過濾。

有什麼解決方法嗎?

+0

什麼是預期的輸出? – jrok

+0

1)爲什麼你改變'forward'中的指定輸出而不是'operator()'中的指定輸出? 2)你可以定義另一個在你的類中定義的函數「層」,並在'apply_filter'中調用它們而不是'forward'。 – dyp

+0

改變每個'std :: cout << ... << std :: endl;'到'std :: cout << forward(...)<< std :: endl;'' –

回答

2

這應該做的伎倆:

#include <iostream> 
#include <utility> 

struct Z { }; 

struct test 
{ 

    using result_type = void; 

    template< typename... P > 
    result_type apply_filter(P &&... _p) const 
    { 
     return operator() (forward<P>(_p)...); 
    } 

    template< typename... T > 
    result_type operator() (std::string const & _s, T &&... _tail) const 
    { 
     std::cout << _s << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

    template< typename... T > 
    result_type operator() (double const & _x, T &&... _tail) const 
    { 
     std::cout << _x << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

    template< typename... T > 
    result_type operator() (Z const &, T &&... _tail) const 
    { 
     std::cout << "z" << std::endl; 
     return operator() (std::forward<T>(_tail)...); 
    } 

private: 

    result_type operator()() const { } 

    template< typename T, typename U > 
    using is_the_same = std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, U>; 

    template<typename T> 
    using is_known_type = typename std::conditional<(is_the_same<T, std::string>::value || is_the_same<T, double>::value), std::true_type, std::false_type>::type; 

    template<typename T> 
    typename std::enable_if<is_the_same<T, std::string>::value, std::string>::type 
    forward_impl(T && _s, std::true_type) const 
    { 
     return "\"" + _s + "\""; 
    } 

    template<typename T> 
    typename std::enable_if<is_the_same<T, double>::value, double>::type 
    forward_impl(T && _x, std::true_type) const 
    { 
     return _x + 1.0; 
    } 

#define RETURNS(exp) -> decltype(exp) { return exp; } 

    template<typename T> 
    auto forward_impl(T && t, std::false_type) const 
    RETURNS(std::forward<T>(t)) 

    template<typename T> 
    auto forward(T && t) const 
    RETURNS(forward_impl(std::forward<T>(t), is_known_type<T>())) 

#undef RETURNS 
}; 

int main(int argc, char ** argv) { 
    test test_; 
    double x = 0.0; 
    std::string s = "s"; 
    Z z; 
    test_.apply_filter(x, s, z); 

    return 0; 
} 
+0

我知道我可以簡單地重複'std :: forward'(對於'T &&'和'T&'版本)「其他」類型的定義(作爲成員函數)。但我更喜歡直接使用std :: forward。但是,在我看來,這是不可能的。 – Orient

+0

如果你想使用'std :: forward',你需要在operator()的內部調用你自己的'forward'(正如我對你的問題的評論中所建議的那樣)。如果你不需要使用'std :: forward',我的答案會告訴你一個辦法。 –

+0

我想特別針對「其他」類型使用'std :: forward',並針對特定類型的某些情況定義了我的過濾器函數。這是因爲'std :: forward'已經存在並且難以寫入兩次相同的功能。 – Orient