6 ms·
How to abuse a C++ compiler?
- michaelfeathers 13y agoI think it is neck and neck whether C++ template instantiation or XSLT is the ugliest unintentional functional programming language.
- alexk7 13y agoI'm pretty sure XSLT functional paradigm was intentional.
- 1ris 13y agoI don't think it's even functional, as it lacks lambdas. It's just pure insane.
- Tobu 13y agoIt's declarative at any rate. It's verbose but as long as it isn't used like an imperative language, I don't find it ugly.
- fhars 13y agoXSLT 2 functional programming was intentional, in XSLT 1 it was more accidentally discovered http://fxsl.sourceforge.net/articles/FuncProg/Functional%20Programming.html http://fxsl.sourceforge.net/articles/FuncProg/Functional%20P...
- xedarius 13y agoI'd say C++ templates are a clear winner in this contest. Simple due to the sheer volume of unintelligible nonsense the compiler produces if there is an error in the template.
- checker659 13y agoClang would beg to differ.
- cousin_it 13y agoI don't understand clang's behavior in the last three examples, but then again I'm not a C++ expert. Is it conforming, and is it reasonable?
- danbruc 13y agoThe answer yes is not reasonable for Russell's paradox and therefore most likely not conforming, too. (Assuming the program really encodes Russell's paradox which I did not try to verify.) UPDATE: Forget the part about conformance - if it is undefined behavior every result is of course correct. I made the wrong assumption that the result should definitely be an error if the correct behavior is not defined or can not be attained.
- Tobu 13y agoClang is mathematically wrong in all but the first case. I'm not sure what it says about C++ conformance; the problem is likely Clang but I'm not sure how sound template metaprogramming or C++ templates are supposed to be.
- aidenn0 13y agoAs others have noted, infinite template recursion is undefined. It could produce a program that does whatever it wants and still be conforming.
- Tobu 13y agoSo the lack of soundness is in the C++ templates spec. Nevertheless, I think it's bad form for a compiler to take full advantage of undefined behaviour. Reinterpreting undefined behaviour as “should not compile” (failing that, “must crash”) is possible for almost all of C99; CompCert (formally verified C compiler) obviously does it, and the implementation is the easy part (formal verification being the complicated part).
- cbsmith 13y ago> So the lack of soundness is in the C++ templates spec. That's not a lack of soundness. It's a lack of specificity. For cases like this, that's actually a feature, not a bug. > Nevertheless, I think it's bad form for a compiler to take full advantage of undefined behaviour. What exactly is "take full advantage of undefined behaviour"? Isn't any behaviour just as different from "undefined" as anything else? > Reinterpreting undefined behaviour as “should not compile” (failing that, “must crash”) is possible for almost all of C99; CompCert (formally verified C compiler) obviously does it, and the implementation is the easy part (formal verification being the complicated part). Clang not only has an ability to do this, it includes a flag to do a quick check specifically for undefined behaviour as well as an ability to provide a trap for undefined behaviour, which is terribly useful for tool builders.
- cordite 13y agoThe first thing I thought was using C++ templates like Haskell.
- zem 13y agoyou should find metafun interesting: http://gergo.erdi.hu/projects/metafun/ http://gergo.erdi.hu/projects/metafun/
- pjmlp 13y agoC++ is not Haskell, but with C++11/C++14 goodies, it does feel a bit closer to it.
- cbsmith 13y agoNot that unusual, though there are some subtle differences in what C++ templates can do.
- jasallen 13y agoas far as I can tell, the Russell's paradox example would be the same without the template "template<typename U, typename V>"? in other words, both compilers seem to be being consistent with the previous demonstrated behavior using self-recursion, and the more generic template is being ignored altogether. Am I perhaps missing a reason it was included?
- vinkelhake 13y agoIt should be noted that at least some cases which previously required template meta programming can now be done in a more natural style with constexpr. A constexpr function can be evaluated at compile time, this means that its return value can be used in places that require a compile time constant. constexpr functions where quite restrictive in C++11. They could pretty much only contain a single expression and a return. C++14 significantly relaxes these restrictions. http://en.wikipedia.org/wiki/C%2B%2B14#Relaxed_constexpr_restrictions http://en.wikipedia.org/wiki/C%2B%2B14#Relaxed_constexpr_res... Type-level meta programming is still confined to using templates though...
- hun-nemethpeter 13y agoI tried to make a proposal for a more natural meta programming: https://github.com/hun-nemethpeter/cpp-reflector-mini/blob/master/Proposal.md https://github.com/hun-nemethpeter/cpp-reflector-mini/blob/m...
- pcwalton 13y agoconstexpr doesn't really help for logic programming though, which is what this post is using template specialization to do. You can't ask for the answer to Russell's paradox using constexpr (which is, IMHO, a good thing).
- pfultz2 13y ago> Type-level meta programming is still confined to using templates though... Which there is less of need for this, since we have better type deduction in C++11 and 14 as well.
- zem 13y agoD has very good support for this. here's a quick string templating function i wrote, for instance: https://gist.github.com/martindemello/2686640 https://gist.github.com/martindemello/2686640 it calls a function at compile time to expand placeholders, and then compiles the generated string via the mixin() statement and carries on with the code. far more pleasant than c++.
- CraigJPerry 13y ago... in order to evaluate InfRec<T>::value ... I've been spoiled lately, this is jarring to read. InfiniteRecursion<T>::value C'mon, spoil me some more, text is cheap :-)
- magnusjonsson 13y agoHorizontal space isn't.
- theophrastus 13y agoFingermann's assertion: at the point where a preprocessor becomes Turing complete it is time to write a preprocessor for it
- unwind 13y agoC++'s template mechanism is not implemented by the preprocessor. Templates control actual code generation (that's sort of their point, with generics) so they must be handled later in the compilation, by the compiler proper.
- ohyes 13y agoIt's funny that in C++ this is 'abuse of the compiler' and it is awkward, in lisp this is called 'writing lisp code'.
- AnimalMuppet 13y agoWell, if you wrote a Lisp macro that recursively called itself until the compiler crashed, you might call that 'abuse of the compiler', too...
- marcosdumay 13y agoThat's because it is awkward. One of the fundamental properties people expect from a step called "compilation" is that it finishes. Also templates notation wasn't designed for this kind of use, and does not scale well for complex programs. In Lisp code generation is done in Lisp, a notation that scales quite well, and there isn't a separarted step called "compilation". There is no general assumption that "execution" finishes.
- cbsmith 13y ago> That's because it is awkward. It's more than a bit awkward really. Still, the OP is right: it's funny.