我想写一个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|
的第一个参数设为&&
,那么一直有效,直到我取消注释filtered()
行,然后我得到:
错误C2825:'R':后跟'::'
时必须是类或命名空间
这样做的正确方法是什么?
答案 0 :(得分:2)
就像它说的那样,标准容器不能存储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; })
);