I want to write a boost adaptor to put at the end of a chain of adaptors to create a collection, like this:
set<string> s = input | filtered(...) | transformed(...) | to_set;
Using Method 3.1 I wrote the code below which seems to work as expected:
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;
}
But if I uncomment that one line, I get:
error C2338: The C++ Standard forbids containers of const elements because allocator is ill-formed.
If I make the first parameter to operator|
be &&
then that works until I uncomment the filtered()
line, and then I get:
error C2825: 'R': must be a class or namespace when followed by '::'
What's the right way to do this?
Like it says, standard containers cannot store const elements. Neither do you want to (because you store copies anyways. If you wanted them const, you can make the container
const
).The fix is:
(removing
const
).Live On Coliru
Prints
PS: You are missing
typename
qualifications (try another compiler than MSVC sometimes)PS: You can
boost::copy_range
: