mirror of
https://github.com/bspeice/speice.io
synced 2024-11-14 05:58:09 -05:00
I was using const_cast<>
incorrectly
This commit is contained in:
parent
fb29d8c9da
commit
5e25faf5fd
@ -117,15 +117,15 @@ public:
|
|||||||
|
|
||||||
Rust allows declaring immutable or mutable.
|
Rust allows declaring immutable or mutable.
|
||||||
|
|
||||||
C++ can use `const_cast` to assert "constness" of `this`:
|
Can require object we're calling methods on to be `const`:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept ConstMethod = requires (T a) {
|
concept ConstMethod = requires (const T a) {
|
||||||
{ const_cast<const T&>(a).method() } -> std::same_as<std::uint64_t>;
|
{ a.method() } -> std::same_as<std::uint64_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::uint64_t my_function(ConstMethod auto a) {
|
std::uint64_t my_function(ConstMethod auto a) {
|
||||||
@ -176,7 +176,51 @@ int main() {
|
|||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
```
|
```
|
||||||
|
|
||||||
...but can't mark `this` as consumed.
|
...which is equivalent to Rust's `&mut self`. Unlike Rust, can't mark `this` as consumed.
|
||||||
|
|
||||||
|
Alternate form: using `static_cast<>` allows mixing some methods that are `const`, some not:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <concepts>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept ConstMethod = requires (T a) {
|
||||||
|
{ static_cast<const T>(a).const_method() } -> std::same_as<std::uint64_t>;
|
||||||
|
{ a.nonconst_method() } -> std::same_as<std::uint64_t>;
|
||||||
|
{ a.unnecessary_const_method() } -> std::same_as<std::uint64_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uint64_t my_function(ConstMethod auto a) {
|
||||||
|
return a.method();
|
||||||
|
}
|
||||||
|
|
||||||
|
class HasConst {
|
||||||
|
public:
|
||||||
|
std::uint64_t const_method() const {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t nonconst_method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concept didn't require this to be `const`, but we can add the qualifier if we want.
|
||||||
|
std::uint64_t unnecessary_const_method() const {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f(ConstMethod auto x) {}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto x = HasConst{};
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
May be better off defining `const T` methods in one concept, `T` methods in another, and then having
|
||||||
|
one concept that `requires` the sub-concepts, but just trying to demonstrate what is possible.
|
||||||
|
|
||||||
Working with `const` parameters can be a bit weird because of implicit copies:
|
Working with `const` parameters can be a bit weird because of implicit copies:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user