5 ms·
There 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: f
by Frizi 4y ago
There 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.
- jcelerier 4y ago> 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. I don't understand how random assumptions on what WG21 may or may not think counts as an example (or anything to be honest) > If something satisfies a Concept, but does not model the Concept then the C++ program is not well formed and no diagnostic is required. uh... no ? I think that you are referring to this blog post: https://akrzemi1.wordpress.com/2020/10/26/semantic-requirements-in-concepts/ https://akrzemi1.wordpress.com/2020/10/26/semantic-requireme... for which I entirely disagree with the whole premise - the only, only thing that matters is what the compiler understands. The standard can reserve itself the right to make some cases UB, such as when trying to sort un-sortable things just like it can state that adding to numbers can cause UB and that's fine: it's the language's prerogative and is all to be treated as unfortunate special-cases ; for the 99.99999% remaining user code, only the code matters and it makes no sense to ascribe a deeper semantic meaning to what the code does. > In which case it's your responsibility to ensure you can log this, which of course CanBlah didn't express. A metric ton of side concerns should not be part of the spec, such as logging, exceptions, etc - everyone saw how terrible and counter-productive checked exceptions were in java for instance. Specifying logging explicitly here would be a -2 in code review as it's purely noise: the default assumption should be that everything can log. > 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. I meant polymorphism, my bad