4 ms·
>That said, I've mostly reached the conclusion that much of this is unavoidable. Systems languages need to have lots of detail you just don't need in higher lev
by logicchains 4y ago
>That said, I've mostly reached the conclusion that much of this is unavoidable. Systems languages need to have lots of detail you just don't need in higher level languages like Haskell or Python, and trait impls on arbitrary types after the fact is very powerful and not something I would want to give up.
Have you checked out C++20 concepts? It supports aliases and doesn't require explicit trait instantiations, making it possible to right such generic code with much less boilerplate.
- loeg 4y agoMy experience in C++ prior to 20 is that it is a lot more verbose/boilerplatey than Rust. I'd love to see that get better, but I think C++ is starting from significantly behind.
- jcelerier 4y agoC++17: template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int>* = nullptr> void func(T fp) { ... } C++20: void func(std::floating_point auto fp) { ... }
- Frizi 4y agoThere is an equivalent syntax in Rust to both of those examples, and in both cases I find it less verbose. The template variant is roughly equivalent to: fn func<T: FloatingPoint>(fp: T) { ... } And the "auto" variant is similar to impl argument in Rust: fn func(fp: impl FloatingPoint) { ... }
- jcelerier 4y agoI really don't see in which way the second case is less verbose especially if you add a non-void return type, e.g. i32. The first case would also be doable like this, which is pretty munch the exact same than your first example with the added "template" keyword template<std::floating_point T> void func(T t) { ... } (also, it's not really equivalent - if I'm not mistaken with traits you can only use what the trait declares ; in C++ you can for instance do something like template<typename T> concept CanBlah = requires (T t) { t.blah(); }; and still be able to do void func(CanBlah auto t) { log << "func:" << t; t.blah(); } instead of polluting the prototype with all possible side concerns)
- tialaramex 4y ago> instead of polluting the prototype with all possible side concerns) C++ Concepts are duck typed, and Rust's Traits are not, so in Rust you are expressing meaning here, and in C++ only making some claims about syntax which perhaps hint at meaning. WG21 seems to dearly wish this wasn't so, offering Concepts which pretend to semantics they don't have, such as std::totally_ordered and I'm glad to see your "CanBlah" concept doesn't do this, to be sure all things which match this requirement can, indeed blah() although we've no idea what that can or should do. Once you've accepted that you only have duck typing anyway, you're probably going to have to explain in your documentation the actual requirements for this parameter t, as the prototype merely says it CanBlah and that's not actually what we care about. In contrast the Rust function we looked at actually does tell us what is required here, something which "implements FloatingPoint", and that implementation (plus the data structure itself) is all that's being exposed.
- jcelerier 4y agoI don't understand - you seem to say that duck typing is a bad thing. In my experience, some parts of a program have to be strongly typed and some have to be "lightly" - I'd say that a good 5% of my work is to make C++ APIs that look&feel closer to dynamic languages with even less typing checks than the C++ baseline. > WG21 seems to dearly wish this wasn't so how so ? > Once you've accepted that you only have duck typing anyway, you're probably going to have to explain in your documentation the actual requirements for this parameter t, as the prototype merely says it CanBlah and that's not actually what we care about. the documentation having to state "t can be logged" would just be useless noise and a definite no-pass in code review aha > In contrast the Rust function we looked at actually does tell us what is required here, something which "implements FloatingPoint", and that implementation (plus the data structure itself) is all that's being exposed. my personal experience from other languages with similar subtyping implementation (ML-ish things) is that this looks good in theory but is just an improductive drag in practice
- tialaramex 4y ago> you seem to say that duck typing is a bad thing C++ didn't have any other practical choice here. But this introduced another case where C++ has a "false positive for the question: is this a program?" as somebody (Chandler Carruth maybe?) has put it. If something satisfies a Concept, but does not model the Concept then the C++ program is not well formed and no diagnostic is required. > how so ? I provided an explanation with an example, and you elided both. > the documentation having to state "t can be logged" would just be useless noise and a definite no-pass in code review aha In which case it's your responsibility to ensure you can log this, which of course CanBlah didn't express. > similar subtyping implementation The only place Rust has subtyping is lifetimes, so that &'static Foo can substitute for any &'a Foo and I don't think that's what you're getting at.