5

ブーストフィルターアダプターを無効にすることは可能/達成可能ですか?

std::vector<int> v = {1, 2, 3, 4, 5};
for(auto i : v | !filtered(is_even))
    std::cout << i << std::endl; // prints 1,3,5

ラムダ式内で否定を行う代わりに?

動機:私はフィルター処理された関数とラムダ関数をよく使用しますが、フィルターを複数回使用する場合は、通常、カスタムフィルターにリファクタリングします。

for(auto i : v | even) // note: my filters are more complex than even.
    std::cout << i << std::endl; // prints 2,4

現在、否定が必要な場合は、それらのカスタムフィルターを作成しています。

for(auto i : v | not_even)
    std::cout << i << std::endl; // prints 1,2,3

しかし、フィルターを無効にできる方がいいと思います。

for(auto i : v | !even)
    std::cout << i << std::endl; // prints 1,2,3
4

2 に答える 2

7

これが私が急いで思いついたものです:

#include <boost/range/adaptors.hpp>
#include <boost/functional.hpp>
#include <iostream>

namespace boost { 
    namespace range_detail { 

        template <typename T>
            auto operator!(filter_holder<T> const& f) -> decltype(adaptors::filtered(boost::not1(f.val)))
            {
                return adaptors::filtered(boost::not1(f.val));
            }
    }
}

int main()
{
    using namespace boost::adaptors;
    int const v[] = { 1, 2, 3, 4 };

    std::function<bool(int)> ll = [](int i){return 0 == (i%2);}; // WORKS
    // bool(*ll)(int) = [](int i){return 0 == (i%2);};           // WORKS
    // auto ll = [](int i){return 0 == (i%2);};                  // not yet

    auto even = filtered(ll);

    for (auto i : v | !even)
    {
        std::cout << i << '\n';
    }
}

liveworkspace.orgでライブでご覧ください

function pointer現在、フォームとの述語を処理していますstd::function<...>が、裸のラムダはまだ処理していないことに注意してください(GCC 4.7.2)

于 2013-02-08T11:12:30.687 に答える
1

これは、フィルターを否定するのではなく、述語のみを否定するため、質問に正確に答えることはできません。解決策を検索すると最初の結果としてこの質問が出たので、私はまだこれを投稿しています。

他の回答と比較すると、これにはカスタムコードをに追加する必要がないという利点がありますnamespace boost::range_detail

C++17ソリューション

この関数std::not_fnを使用して、否定された述語を作成できます。

#include <boost/range/adaptors.hpp>
#include <functional>
#include <iostream>

struct is_even
{
    bool operator()( int x ) const { return x % 2 == 0; }
};

int main()
{
    using namespace boost::adaptors;
    int const v[] = { 1, 2, 3, 4 };

    for( auto i : v | filtered( std::not_fn( is_even{} ) ) )
    {
        std::cout << i << ' ';
    }
}

ライブデモ

C ++ 11、C++14ソリューション

この関数std::not1を使用して、否定された述語を作成できます。述語がメンバータイプを定義する必要があるという追加の要件があります。これは、述語パラメーターargument_typeと同じタイプです。operator()

#include <boost/range/adaptors.hpp>
#include <functional>
#include <iostream>

struct is_even
{
    using argument_type = int;
    bool operator()( int x ) const { return x % 2 == 0; }
};

int main()
{
    using namespace boost::adaptors;
    int const v[] = { 1, 2, 3, 4 };

    for( auto i : v | filtered( std::not1( is_even{} ) ) )
    {
        std::cout << i << ' ';
    }
}

ライブデモ

于 2019-01-11T12:06:16.543 に答える