【问题标题】:boost range adaptor that makes a collection进行收藏的升压范围适配器
【发布时间】:2017-11-30 01:31:49
【问题描述】:

我想写一个 boost 适配器放在一个适配器链的末尾来创建一个集合,像这样:

set<string> s = input | filtered(...) | transformed(...) | to_set;

使用Method 3.1 我编写了下面的代码,似乎可以按预期工作:

namespace detail
{
    struct to_set_forwarder
    {
    };
};

template <class R> inline auto operator|(R& r, detail::to_set_forwarder)
{
    return set<R::value_type>(r.begin(), r.end());
}

template <class R> inline auto operator|(const R& r, detail::to_set_forwarder)
{
    return set<const R::value_type>(r.begin(), r.end());
}

namespace
{
    const auto to_set = detail::to_set_forwarder();
}

void F()
{
    vector<string> input{ "1", "2", "3" };
    auto result = input
        //| boost::adaptors::filtered([](const auto& _) { return true; })
        | to_set;
}

但如果我取消注释那一行,我会得到:

错误 C2338:C++ 标准禁止 const 元素的容器,因为分配器格式错误。

如果我将operator| 的第一个参数设为&amp;&amp;,那么直到我取消注释filtered() 行,然后我得到:

错误 C2825:“R”:后跟“::”时必须是类或命名空间

这样做的正确方法是什么?

【问题讨论】:

    标签: c++ boost boost-range boost-adaptors


    【解决方案1】:

    正如它所说,标准容器不能存储 const 元素。你也不想(因为无论如何你都存储副本。如果你想要它们 const,你可以创建容器 const)。

    解决方法是:

    template <class R> inline auto operator|(const R& r, detail::to_set_forwarder)
    {
        return std::set<typename R::value_type>(r.begin(), r.end());
    }
    

    (删除const)。

    Live On Coliru

    #include <boost/range.hpp>
    #include <boost/range/adaptors.hpp>
    #include <set>
    #include <vector>
    #include <iostream>
    #include <string>
    
    namespace detail
    {
        struct to_set_forwarder
        {
        };
    }
    
    template <class R> inline auto operator|(R& r, detail::to_set_forwarder)
    {
        return std::set<typename R::value_type>(r.begin(), r.end());
    }
    
    template <class R> inline auto operator|(const R& r, detail::to_set_forwarder)
    {
        return std::set<typename R::value_type>(r.begin(), r.end());
    }
    
    namespace
    {
        const auto to_set = detail::to_set_forwarder();
    }
    
    void F()
    {
        std::vector<std::string> input{ "1", "2", "3", "2" };
        auto result = input
            | boost::adaptors::filtered([](const auto& _) { return true; })
            | to_set;
    
        for (auto x : result)
            std::cout << x << " ";
    }
    
    int main() {
        F();
    }
    

    打印

    1 2 3
    

    PS:您缺少typename 资格(有时尝试使用 MSVC 以外的其他编译器)

    PS:你可以boost::copy_range

    auto result = boost::copy_range<std::set<std::string> >(input
        | boost::adaptors::filtered([](const auto& _) { return true; })
        );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-14
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-14
      • 2017-10-30
      • 2014-02-19
      相关资源
      最近更新 更多