From 5e25faf5fd965ff8f743a8cb2cb140c2db9bbee5 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Sun, 30 Aug 2020 03:03:15 -0400 Subject: [PATCH] I was using `const_cast<>` incorrectly --- _posts/2020-08-05-static-polymorphism.md | 52 ++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/_posts/2020-08-05-static-polymorphism.md b/_posts/2020-08-05-static-polymorphism.md index f2ecb4e..b8dda6f 100644 --- a/_posts/2020-08-05-static-polymorphism.md +++ b/_posts/2020-08-05-static-polymorphism.md @@ -117,15 +117,15 @@ public: 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++ #include #include template -concept ConstMethod = requires (T a) { - { const_cast(a).method() } -> std::same_as; +concept ConstMethod = requires (const T a) { + { a.method() } -> std::same_as; }; 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 +#include + +template +concept ConstMethod = requires (T a) { + { static_cast(a).const_method() } -> std::same_as; + { a.nonconst_method() } -> std::same_as; + { a.unnecessary_const_method() } -> std::same_as; +}; + +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: