微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 如何为random_shuffle编写range-v3动作?

使用 range-v3 library(由@EricNiebler),使得编写算法代码更加紧凑,例如这是如何生成一堆随机数:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>

int main() 
{
    using namespace ranges;

    auto const N = 10;
    std::vector<int> v; 
    v.reserve(N);

    v |= action::push_back(view::iota(0,N)); 
    random_shuffle(v);
    copy(v,ostream_iterator<>(std::cout,","));
}

Live Example.

但是,我更愿意使用假设的动作:: random_shuffle()来扩展管道

v |= action::push_back(view::iota(0,N)) | action::random_shuffle();

这是我尝试编写这样的动作(不幸的是,编写新的range-v3代码比使用库更加冗长)

#include <functional> // bind,placeholders::_1

namespace ranges
{
    inline namespace v3
    {
        /// \addtogroup group-actions
        /// @{
        namespace action
        {
            struct random_shuffle_fn
            {
            private:
                friend action_access;

                static auto bind(random_shuffle_fn random_shuffle)
                RANGES_DECLTYPE_AUTO_RETURN
                (
                    std::bind(random_shuffle,std::placeholders::_1)
                )

                template<typename Gen>
                static auto bind(random_shuffle_fn random_shuffle,Gen && rand)
                RANGES_DECLTYPE_AUTO_RETURN
                (
                    std::bind(random_shuffle,std::placeholders::_1,bind_forward<Gen>(rand))
                )
            public:
                struct ConceptImpl
                {
                    template<typename Rng,typename I = range_iterator_t<Rng>>
                    auto requires_(Rng&&) -> decltype(
                        concepts::valid_expr(
                            concepts::model_of<concepts::RandomAccessRange,Rng>(),concepts::is_true(Permutable<I>())
                        ));
                };

                template<typename Rng>
                using Concept = concepts::models<ConceptImpl,Rng>;

                template<typename Rng,CONCEPT_REQUIRES_(Concept<Rng>())>
                Rng operator()(Rng && rng) const
                {
                    ranges::random_shuffle(rng);
                    return std::forward<Rng>(rng);
                }

                template<typename Rng,typename Gen,CONCEPT_REQUIRES_(Concept<Rng>())>
                Rng operator()(Rng && rng,Gen && rand) const
                {
                    ranges::random_shuffle(rng,std::forward<Gen>(rand));
                    return std::forward<Rng>(rng);
                }

                #ifndef RANGES_DOXYGEN_INVOKED
                template<typename Rng>
                void operator()(Rng &&) const
                {
                    CONCEPT_ASSERT_MSG(RandomAccessRange<Rng>(),"The object on which action::random_shuffle operates must be a model of the "
                        "RandomAccessRange concept.");
                    using I = range_iterator_t<Rng>;
                    CONCEPT_ASSERT_MSG(Permutable<I>(),"The iterator type of the range passed to action::random_shuffle must allow its "
                        "elements to be permuted; that is,the values must be movable and the "
                        "iterator must be mutable.");
                }
            #endif
            };

            /// \ingroup group-actions
            /// \relates sort_fn
            /// \sa `action`
            namespace
            {
                constexpr auto&& random_shuffle = static_const<action<random_shuffle_fn>>::value;
            }
        }
        /// @}
    }
}

Live Example无法编译,因为某些operator()深藏在某处未找到.

据我所见,我忠实地从类似的代码中转换了上述代码,例如action :: sort().唯一的区别是random_shuffle()有两个重载(一个采用随机生成器),而所有其他动作(包括sort)都有一个重载,其额外参数的认值(比较器,谓词,投影仪等) .这转换为上面的random_shuffle_fn的两个bind()静态成员函数,而所有其他操作只有一个bind()重载.

问题:如何为random_shuffle编写range-v3动作?

解决方法

你有两个不明确的random_shuffle_function :: operator()(Rng&&)重载,你的“错误捕获”重载需要被限制为只接受那些正确的重载拒绝的参数(我们真的需要C Concepts所以我再也没有了到SFINAE约束重载):
#ifndef RANGES_DOXYGEN_INVOKED
template<typename Rng,CONCEPT_REQUIRES_(!Concept<Rng>())>
void operator()(Rng &&) const
{
    CONCEPT_ASSERT_MSG(RandomAccessRange<Rng>(),"The object on which action::random_shuffle operates must be a model of the "
        "RandomAccessRange concept.");
    using I = range_iterator_t<Rng>;
    CONCEPT_ASSERT_MSG(Permutable<I>(),"The iterator type of the range passed to action::random_shuffle must allow its "
        "elements to be permuted; that is,the values must be movable and the "
        "iterator must be mutable.");
}
#endif

此外,您需要管道操作:: random_shuffle:

v |= action::push_back(view::iota(0,N)) | action::random_shuffle;

DEMO

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐