简体   繁体   中英

How should you create a std::experimental::observer_ptr to a non-const object that cannot mutate the value it points to?

Is this the canonical way to create a std::experimental::observer_ptr to a non- const object that cannot mutate the value it points to?

auto i = int{0};

auto p = std::experimental::make_observer(&std::as_const(i));
*p = 1; // compilation error, as desired

https://godbolt.org/z/h3Uq0o

EDIT:

What if the pointer already exists (which I suppose is the more common use-case)? Would we have to const_cast ?

auto i = int{0};
auto p = &i;

auto q = std::experimental::make_observer(const_cast<const int*>(p));
*q = 1; // compilation error, as desired

https://godbolt.org/z/NbR6Nj

Don't complicate matters. Just do

observer_ptr<const int> p{&i};

And everything is fine.

You can also do this according to the spec :

observer_ptr p{&std::as_const(i)};

but GCC and Clang seems to diverge from the spec here. The implementation uses a qualified name for the (element_type*) constructor, therefore blocking class template argument deduction.


Much like std::make_pair , make_observer exists because the library fundamentals 2 TS is created in pre-C++17 era. Class template argument deduction wasn't a thing at that time. Nowadays, we rarely need a separate make function like std::make_pair (counterexample: reference wrappers, see Usefulness of std::make_pair and std::make_tuple in C++1z ), and similarly we rarely need make_observer .

Therefore, it doesn't make much sense to talk about the "canonical" way of using a pre-C++17 feature like observer_ptr in C++17. Granted, we can use class template argument deduction if it actually works. That's simply not even considered in the design of observer_ptr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM