This is a follow-up question to Why std::stable_sort does not compile when std::sort does?
The problem is the same, except the simplify
is now called get_const
and returns a smart pointer to the const X
.
The bigger picture is that I want to have a container of X
, that can be cast (without copying) to a container of const X
. Currently I implemented it as a base class ContainerOfConstX
that holds std::vector<std::experimental::propagate_const<std::shared_ptr<X>>> _m
and two views: one _const = _m | std::views::transform(get_const);
and the other as _mutable = _m | std::views::transform(simplify);
. There is a Derived class ContainerOfX
that serves functions based on _mutable
.
All two containers expose the natural functions to their names, such as begin()
, end()
, front()
, back()
, push_back(std::shared_ptr<[const] X>)
, etc. with the expected semantics.
#include <ranges>
#include <vector>
#include <experimental/propagate_const>
#include <memory>
#include <algorithm>
struct X {
X(int x) : mx(x) {}
int mx;
};
std::shared_ptr<const X>& get_const(std::experimental::propagate_const<std::shared_ptr<X>>& i) {
return get_underlying(i); // error: invalid initialization of reference of type ‘std::shared_ptr<const X>&’ from expression of type ‘std::shared_ptr<X>’
}
int operator<=>(const std::shared_ptr<X>& lhs, const std::shared_ptr<X>& rhs) {
return 0;
}
int main() {
std::vector<std::experimental::propagate_const<std::shared_ptr<X>>> m; //originally a member variable of a class that works as custom container of X.
m.push_back(std::make_shared<X>(4));
m.push_back(std::make_shared<X>(2));
m.push_back(std::make_shared<X>(3));
m.push_back(std::make_shared<X>(1));
// Some code that works with vector of non-const Xs.
decltype(m | std::views::transform(get_const)) r = m | std::views::transform(get_const);
// Some code that works with vector of const X. In particular:
std::sort(r.begin(), r.end());
std::stable_sort(r.begin(), r.end());
}
Maybe the issue is with the std::experimental::propagate_const
? I would very much prefer not to use it at all, because in the end I need to target msvc as well.
Please note, that making the argument to get_const
const gets the code compile (not on clang, though), with the warning message: warning: returning reference to temporary: return get_underlying(i)
Godbolt link
3