I have inherited a large data science project in C++20. To aid reasoning through the code I started to enforce const-correctness. The project involves classes that expose vectors of smart pointers and functions that can work with read-only versions of those, i.e. with const vectors of const pointers to const objects.
Is the question of propagation solved in C++20?
How to make the marked line to compile without making extra copy of the widget vector?
I know I can solve the problem by changing the API of the class A and expose iterators rather than vectors. I would very much prefer no to change the API – enforcing const-correctness is a chore large enough, and I really don’t want to task myself with adding new semantics to the code.
I cannot work without smart pointers, because there is no clear owner of Widgets in my problem domain.
I am aware of https://en.cppreference.com/w/cpp/experimental/propagate_const – it does not work with containers, and nesting it inside container like this std::vector<std::experimental::propagate_const<std::shared_ptr<Widget>>> widgets_
does not allow for const propagation.
The closest existing question in SO: How can I propagate const when returning a std::vector<int*> from a const method?. The solution offered there does not work with smart pointers.
Here’s the code that illustrates my problem.
struct Widget {
int x;
int y;
};
class A {
public:
A() : widgets_() { widgets_.push_back(std::make_shared<Widget>(1, 2)); }
[[nodiscard]] std::span<const std::shared_ptr<const Widget>> getConstWidgets() const { return widgets_; } // This line does not compile.
private:
std::vector<std::shared_ptr<Widget>> widgets_;
};
void do_something_with_const(std::span<const std::shared_ptr<const Widget>>);
void main() {
A a;
do_something_with_const(a.getConstWidgets());
}