I hated writing modern C++. It was just so depressing and frustrating.
I hated writing modern C++. It was just so depressing and frustrating.
1. the actual type is clearly visible on the right hand side. auto f = make_widget(); // it's a widget auto i = 123; // it's an int auto x = vec3(1.0, 0.0, 0.0); // it's a vector
2. the actual type doesn't really matter so much or is complicated to type out. auto it = vec.begin(); // it's an iterator auto it = // some template expression
3. the actual type is not known i.e. lambdas
auto f = make_widget();
// is f of type widget or widget*?
auto i = 123;
// ok, I guess, but...
// int i = 123; is shorter and more clear.
auto x = vec3(1.0, 0.0, 0.0);
// this can be shorter and simpler.
// vec3 x(1.0, 0.0, 0.0);I fail to see how this line is supposed to be a "criticism" of modern C++.
However I have came to realize that I rather use it on as an infrastructure language.
Just when I need to write portable code across mobile OSes without dependencies on third party SDKs, interact with LLVM or give an helping hand to my actual daily programming languages.
let x = someFunction()
Alt-click on x and it shows the type.
Otherwise, as you say, the code becomes very confusing and I abstain from auto except in cases where the type is clearly obvious.
class A { B: b}
class B { a: A}
Long story short - I was to create a wrapper around a Poco::Runnable, so you can use the wrapper as a Poco::Runnable (don't ask why, it's TEH LAW) but without extending it.Disallowing cyclical dependencies via pointer would make no sense though.
After spending about 10-12 years away from C++, I was pretty much on novice level. I remember some things, but most details and day to day specifics are gone. It did serve as a fresh reminder why I hate C++. Or more precisely, why I hate C++ compilers.
class B;
class A {
B* b;
}
class B {
A* a;
}
because the compiler can (obviously) not tell how large the instances of the other class are when you have a field of that type. Remember that the class layout has to be fixed at compile time and both instance sizes depend on one another. That's not solvable.C# does the same, actually:
struct A {
B b;
}
struct B {
A a;
}
will cause the following error: test.cs(2,5): error CS0523: Struct member 'A.b' of type 'B' causes a cycle in the struct layout
test.cs(6,5): error CS0523: Struct member 'B.a' of type 'A' causes a cycle in the struct layout
with classes and references it works, of course: class A {
B b;
}
class B {
A a;
}I spent good solid 30min trying to understand why defining and not defining my constructor was causing issues, to realize that the constructor error was actually a previous error, somewhere above the constructor.
Rust, also notes where and how you created an infinite loop.
class A; class B; // 'forward declaration' if you want to google
class A { unique_ptr<B> b; };
class B { unique_ptr<A> a; };
...generally classes instantiating each other is a sign that your design needs rearranged, but it has its uses when writing graph types. class B;
class A { B* b;}
class B { A* a;}I've added a few of those talks I've watched and liked to a small playlist (with a couple of other talks on programming, unrelated - the relevant talks are prefixed with "cppcon 2015"):
https://www.youtube.com/playlist?list=PLHvt7sld3hmvdDnwHkdU2...
The full cppcon playlist is here: https://www.youtube.com/playlist?list=PLHTh1InhhwT75gykhs7pq...
Of special relevance is the rather excellent talk by Kate Gregory on "Stop Teaching C" (when you're supposed to do an intro course to C++):
"CppCon 2015: Kate Gregory “Stop Teaching C"": https://www.youtube.com/watch?v=YnWhqhNdYyk
(But again, I want an open wiki/live tutorial, along the lines of "How I start", but longer, which goes through all this stuff. We really should make one, both for C++14 and for C11).
CppCon 2015: Herb Sutter "Writing Good C++14... By Default": https://www.youtube.com/watch?v=hEx5DNLWGgA Is also rather uplifting, and:
CppCon 2015: Sean Parent "Better Code: Data Structures": https://www.youtube.com/watch?v=sWgDk-o-6ZE
makes a pretty good case for simple, modern C++ being clear, easy and efficient.
Finally,
CppCon 2015: Phil Nash “Test Driven C++ with Catch”: https://www.youtube.com/watch?v=gdzP3pAC6UI
apart for being a pretty straight forward intro to a simple testing framework, appears to reveal some secrets combining template magic and still get sane compile times (hint: don't recompile more (template) code on every iteration than you need to).
There's a couple of good ones that touch on meta-programming too (Look for the talk on Spirit X3 and Brigand), and there's a nice lightning talk on clang-tidy (magically go from explicit loops to modern foreach, yay!).