> It sucks. Trust me - writing kernel code in C++ is a BLOODY STUPID IDEA.
C++ has evolved tremendously since. There are better arguments.
(and I say this as a C developer who doesn't believe C++ is the right answer)
(not that I'm arguing for C++ in linux or such)
Recently created a third party SDK DLL in c++ and could not pass c++ types natively (unless you coupled to compiler and maybe version of compiler).
The important part is that it is used by most, if not all, C++ compilers on that platform.
UWP now even supports generics and actual inheritance.
* C++ has advanced considerably, and features like constexpr, lambas, unique_ptr, etc make writing code easier without runtime overhead.
* The C Compiler that Linux uses, is now written in C++
* Clang tidy checks make it relatively easy to keep problematic C++ features out.
The fact that C++ is largely a superset of C means that just like GCC did, there can be a gradual migration of code.
...and gained considerable complexity in the process. (I'm aware that C has gained some too, but not to the extent of C++.)
This is not the case for evolving C++.
And yes, the fact that abi stability isn't really a thing in c++ land is a huge problem too. It has been tried before with beos and it sucked.
template<typename _Tp>
_GLIBCXX14_CONSTEXPR
inline const _Tp&
max(const _Tp& __a, const _Tp& __b)
{
// concept requirements
__glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
//return __a < __b ? __b : __a;
if (__a < __b)
return __b;
return __a;
}
I mean, there are more overloads, but it isn't what I'd call huge.To be honest, I'm just a bystander here but I did actually find the C based max() presented easier to appreciate than the C++ one you present here.
The C one looks more like a maths proof: build the argument ... et voila. It also does not have comments inline because it is a sort of comment. The C++ version has two inline comments, one of which is incorrectly formatted (space or no space after indicator) and the second one seems superfluous because it uses code to describe code. The C++ version, after you strip out the comments, looks very concise. If it does the same job then good stuff. After that we are down to whether x,y is a better choice than a,b. On balance I prefer a,b for arbitrary inputs and x,y etc for functional dependent - so the C++ example wins here for me.
This seems like the kind of thing which is easily corrected and probably not relevant for determining which is the better approach.
That chunk of code is one of the fundamental building blocks of C++. When presented as exhibit A it should look good. To an outsider that sort of thing looks bad, even if the presented thing is correct the silly error will be obsessed over - as here.
If something is important enough, and I think that C++ is one of those, then for $DEITYS sake fix the obvious stuff before having to be an apologist for it. A simple sed script run decades ago would have done that.
The reason I am labouring this point is that one day it wont be a discussion on HN debating this sort of bollocks but something involving lots of dosh. If S&M ever realised what source code really looked like - they'd have a fit. The world turns ...
It makes sense to drop the space before the start of the commented code because that way you can just delete the // and obtain the original source line.
}
int foo(){
for(x=1; x<len*2;x++){//over 2 array len
...(no empty lines for next hour)
I know I’m clinical perfectionist, but try to see it behind my complaint. Our brain can process only few things in parallel. If you overload it with parsing and do not provide hints like grouping and/or formatting, you occupy a couple of threads for a complete bs. As if programming was not one of the hardest things already.In practice, the style for writing STL code is often quite ugly (sometimes deliberately ugly), for reasons which aren't really interesting to most people.
It’s not unusual to use a space after // for comments and no space for code that has been commented out.
...
#define __is_constant(x) \
(sizeof(int) == sizeof(*(1 ? ((void*)((long)(x) * 0l)) : (int*)1)))
...
How many C programmers would even understand what that code does, without an explanation? template<class T> constexpr T max(T l, T r) {return l < r ? r : l;}All the crazyness is in order to support both constant expressions (and keep them constant expressions) and non-constant expressions with the same max() macro.
>The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed (provided that appropriate function arguments are given).
T max(T)(T a, T b) { return a < b ? b : a; }
without requiring explicit constexpr annotations and with less noisy template syntax ;).Or what edflsafoiewq said: https://news.ycombinator.com/item?id=16721559
It is however trivial to write a version that works with distinct types, if that were really what you want.
template<class L, class R>
constexpr std::common_type_t<L, R> max(L l, R r) {return l < r ? r : l;}This is a property of c++ implicit constructor rules, it is not unique to this function. In most cases this is something you want to avoid but for integer promotion it can some times be useful.
int* x = malloc(5 * sizeof (int));
because in C++ you cannot implicitly cast a void pointer. max<int>(-1, 2u) // => 2