5 ms·
You shouldn't compare C++ templates to Rust polymorphism. The latter is decidable, the former is not. Compare C++ templates to Rust macros. Btw. Who likes C++
by choeger 5y ago
You shouldn't compare C++ templates to Rust polymorphism. The latter is decidable, the former is not. Compare C++ templates to Rust macros.
Btw. Who likes C++ templates? They are such a roundabout way to program the compiler that it regularly hurts me. You need to understand a set of arbitrary rules (steered by implementation of the existing compilers, not language design, it seems) to make the compiler do what you want in many lines of code. And only fellow template lovers will have a chance to understand your intention. It is admittedly powerful, but compared to any decent macro implementation (Lisp, Haskell, OCaml, Rust) it is so much worse...
- salicideblock 5y ago> Btw. Who likes C++ templates? Saying I like them is a stretch, but I prefer to write a C++ template rather than a macro (C++ or Rust) any day.
- mlindner 5y agoC++ macros are completely unlike Rust macros so lumping them together makes no sense.
- edflsafoiewq 5y agoTemplates are not very much like macros. You cannot perform a syntactic rewrite at the point of instantiation that replaces the template use, and they are integrated into the semantics of eg. overload resolution in a way syntactic macros obviously can't be. I don't see why decidability should render them incomparable.
- choeger 5y ago> they are integrated into the semantics of eg. overload resolution in a way syntactic macros obviously can't be. Exactly, they are macros that can only be invoked via some weird implicit entry points. Proper macros could be used very much in the same way, of course, if the compiler recognizes their output correspondingly. You could, for instance, use macros to generate traits/type classes to enhance overloading. Why someone would prefer this code generation to be so implicit, I don't understand. > I don't see why decidability should render them incomparable. Of course you can compare them if you want to point out that particular difference. But if you claim that templates are more powerful, the obvious answer is: Sure, because they're not type safe. Templates simply aren't a type system extension, they're more like macros.
- MauranKilom 5y ago> Sure, because they're not type safe. Templates simply aren't a type system extension, they're more like macros. Could you elaborate in which way C++ templates are not type-safe? Does the upcoming concepts feature alleviate any of it?
- choeger 5y agoA type safe language has a deterministic, terminating algorithm that can prove the absence of certain errors in a program. For instance you cannot use integers instead of functions in well-typed a Haskell program whereas you can make this mistake in a python program. C++ Templates are not type safe because they need to be evaluated before you can make any statement about their successful, correct application. This evaluation might not terminate. Macros habe the same issue, of course, but they explicitly give you a Turing-complete programming language so it feels more natural.
- moth-fuzz 5y agoC++ is a fully compiled language, and will not compile code that has type errors (barring you hack your way out of the spirit of the type system). Templates are no exception - they are type-safe once instantiated because they transform at that point into normal C++, which is type safe. Templates themselves are not types and are not meant to be, they’re meant to be templates, yes, more akin to macros, but not at any cost or defecit because of it. Frankly I don’t understand the criticism; I don’t care if I get a compiler error during template evaluation or during compilation or during linkage, a compiler error is a compiler error. Code that works works and code that doesn’t doesn’t.
- choeger 5y ago> Frankly I don’t understand the criticism; I don’t care if I get a compiler error during template evaluation or during compilation or during linkage, a compiler error is a compiler error. You might want to consider a setup where the library author is not the same person as the library user. Don't you think it's important that the former sees and not the latter? That's why linker errors and compiler errors and template errors are not equal. Also, if you make an error in a template or its instantiation you might not even get an error but an infinite (i.e., maybe aborted) computation. If you don't see the difference between these things, I cannot help you.
- mgaunard 5y agoTemplates are just what their name says: recipes to generate types or functions. They work very well and are quite pleasant to work with. I don't really see what's so complicated about them.
- choeger 5y agoThe complication of templates arises from the fact that you need to know the inner workings of a C++ compiler instead of just a language definition. I know that C++ is specified in a very implementation-oriented manner and I also know that many developers don't see the difference, but design ain't implementation. If you have proper macros you don't need to know the compiler internals. You have an API that generates code with the language semantics you already know. By definition that's simpler. It's also more powerful, btw.
- mgaunard 5y agoThat is just not true. Compiling C++ is a very complicated task, I'd guess that there are less than a hundred people in the world with the experience of implenting a standard-conforming C++ compiler, and there are a lot more developers comfortable with templates. What exactly is your perceived problem? You need to have the template definition in order to instantiate it; that is pretty logical. Is this kind of basic common sense what you call "knowing the inner workings of the compiler"?
- choeger 5y agoWhere shall I start? Template specialization order? Recursive template definitions for variadic arguments? Conditional template arguments? std::enable_if ?
- mgaunard 5y agoTemplate specialization works under the same rules as overloading with some restrictions (this is actually how it is formally defined). The first step prior to overload resolution is name lookup, which discards template candidates whose declaration refers to dependent names on template parameters which wouldn't exist for that implicit instantiation. The only order that matters is what specializations are visible at the time of the instantiation, and adding more specializations after that is more likely than not to lead to ill-formed programs (due to the ODR rule that you must satisfy), so you can assume it doesn't happen. enable_if, recursion or whatever else you're referring to are merely trivial applications of the rules. I don't think it's unreasonable to have to understand how overloads are selected in order to program in C++. The semantics were not designed to match an implementation but rather to make the most sense. This has nothing to do with compiler internals; if anything many compilers implemented it incorrectly for decades.
- moth-fuzz 5y agoI mean, if you could tell from my original post, I like C++ templates. The point is not to constantly write templates in your calling code, the point is to architect a library with templates that affords flexibility and dynamism so that the calling code is easy to write, read, and reason about. Consider, for example, the sol2[0] example usage code vs the actual source code itself[1]. 0. https://github.com/ThePhD/sol2 https://github.com/ThePhD/sol2 1. https://github.com/ThePhD/sol2/blob/develop/include/sol/function_types.hpp https://github.com/ThePhD/sol2/blob/develop/include/sol/func...
- tempodox 5y agoRe OCaml: For what a C++ template does, you'd use a parameterized module (“functor”), not a macro. The OCaml macro equivalent would be a PPX rewriter, which is a rather heavy-handed approach to metaprogramming.
- choeger 5y agoNo. An ML-style functor is well-designed and can be type checked at the site of definition. If C++ had functors I would be very happy, but functors are not "zero cost" abstractions..., maybe they can be in a compiler like MLton, though.
- tempodox 5y agoI was referring to the use case, not the implementation details. ML-style functors may not be zero-cost abstractions, but they are a way to implement polymorphism, just like C++ templates. You may be able to achieve that with a PPX rewriter, but I'd rather use a functor.
- otabdeveloper4 5y agoYou realize that C++ templates are just a compile-time Lisp-like language interpreter, right?
- josh11b 5y agoI don't think Rust polymorphism is decidable: https://sdleffler.github.io/RustTypeSystemTuringComplete/ https://sdleffler.github.io/RustTypeSystemTuringComplete/
- choeger 5y agoWell, shit. They broke the language. I still hope that a reasonable subset of the type system remains decidable, though.