Your post is very ranty, i disagree with lots, but I think you’re flat out wrong here:
> Turns out it's a LOT easier to have 2 discrete functions explicitly doing the same thing than using a template
How do you write containers? I tried following a series on implementing an interpreter in c a few months ago, but gave up because 30% of the code was implementing std::vector for different types.
Also, math routines definitely work better templated. Code duplication isn’t always bad but if your methods are copy and pasted with different signatures, that sucks. E.g. an interpolation method that works on double and floats.
> ome idiot colleague won't decide that the string creation class constructor shouldn't take a reference, but a copy, making the app startup take 30 seconds with ONE character '&' removal.
This isn’t an argument against c++, this is an argument against your co workers. The exact same argument could be made for C with removing two * signs.
C has it’s fair share of gotchas thy you don’t refularly hit in c++ too - malloc requiring sizeof, not checking realloc’s return values, goto hell for resource cleanup, complicated lifetimes.. personally I’d rather have C++, warts and all, than have to deal with the “simplicity” of reimplementing a stack in every resource owner, and reimplementing vector/map for every type.
A 1-line macro is not bad. stb's stretchy_buffer is not bad, but it could do with less macros. Take the ones from my own example that I linked elsewhere on this page.
If you use macros "correctly" there is rarely any logic in there, and they are decidedly not hard to debug. Macros let you do things that you could not do otherwise, like getting information about the caller or the size of the element type that is abstracted behind a void ptr.
C++ templates on the other hand - if you have considerable C++ experience you will shy them. They drive compile times up insanely, and are actually very difficult to debug, at least under "normal" usage.
Also, code bloat results after a few instanciations where a simple runtime integer could be used to discriminate between different cases, but with shared implementation code.
I would never again touch even the most basic C++ template, that is std::vector. I prefer my simple 3 lines of macros.
> How do you write containers? I tried following a series on implementing an interpreter in c a few months ago, but gave up because 30% of the code was implementing std::vector for different types.
You can use the preprocessor to generate these discrete functions and data structures. A simple example implementing just a linked list data structure:
list_generic.h:
#define CATH(a, b) a ## b
#define CAT(a, b) CATH(a, b)
struct CAT(T, _list) {
T value;
struct CAT(T, _list) *tail;
};
list.h:
#define T int
#include "list_generic.h"
#undef T
#define T float
#include "list_generic.h"
#undef T
typedef char * string;
#define T string
#include "list_generic.h"
#undef T
Then you'll end up with int_list, float_list and string_list structs.
Not saying that this is pretty or particularly satisfies the goal of being explicit and readable, but it's possible if you can accept different type and method names for the different contained types.
> Turns out it's a LOT easier to have 2 discrete functions explicitly doing the same thing than using a template
How do you write containers? I tried following a series on implementing an interpreter in c a few months ago, but gave up because 30% of the code was implementing std::vector for different types.
Also, math routines definitely work better templated. Code duplication isn’t always bad but if your methods are copy and pasted with different signatures, that sucks. E.g. an interpolation method that works on double and floats.
> ome idiot colleague won't decide that the string creation class constructor shouldn't take a reference, but a copy, making the app startup take 30 seconds with ONE character '&' removal.
This isn’t an argument against c++, this is an argument against your co workers. The exact same argument could be made for C with removing two * signs.
C has it’s fair share of gotchas thy you don’t refularly hit in c++ too - malloc requiring sizeof, not checking realloc’s return values, goto hell for resource cleanup, complicated lifetimes.. personally I’d rather have C++, warts and all, than have to deal with the “simplicity” of reimplementing a stack in every resource owner, and reimplementing vector/map for every type.