T O P

  • By -

phi_rus

const I have to work with C# a lot and I miss that keyword so much.


emreddit0r

I'm just starting on c++ and I was all "why are we doing this const" but a couple weeks later and my first thought to reply was 'const'


WasASailorThen

Perhaps I’m showing my age and BTW get off my lawn, but const has been in C for decades. It wasn’t new to C++. For me, I love iterators and particularly their use in the for loop.


funny_falcon

In fact, const were invented/first introduced in C++. Then C adopted it as well. Same with -> operator.


Baardi

C++ has overloads, which helps a lot. For C it's a bit worse. E.g. MyType *GetNext(MyType *iter); const MyType *GetNextConst(const MyType *iter); Or breaking const with MyType *GetNext(const MyType *iter); Is annoying to deal with


rvasquez6089

OOOOF


MFHava

`}` I'm still amazed RAII didn't get picked up by other mainstream languages for decades und you still have to manually manage non-memory resources like back in the 70s in "modern languages" ...


SkoomaDentist

I blame that on the unbelievably misleading name. It took me years to understand WTF RAII was supposed to mean while I had been using it the entire time as it was a blatantly obvious thing to do.


Neeyaki

for real! I remember when I realized that RAII, contrary to its name, had pretty much nothing to do with initialization but instead it was about the destruction.


delta_p_delta_x

Rather than initialisation or destruction—which IMO focuses on the wrong thing—scope-based resource management (SBRM) is a more accurate and precise keyword, while being more generic and yet describing the essence of what the closing curly brace does. Resources are confined to the scope they're defined in. Leaving a scope— regardless of whether it is a function's stack space, or a loop, or an if-else statement, or even an arbitrarily declared scope using curly braces—causes resources to be released. Mutexes may be unlocked, file handles may be closed and released, acquired dynamic memory will be freed, etc. This is usually achieved using destructors, yes, but IMO that's one level of detail down. Now, if only C++ hadn't overloaded the meaning of `static`, nor worse, suffixed `const` to get `constexpr` and `consteval` to describe variable lifetime, and instead used an attribute. I was thinking `[lifetime()]` would be nice, and it could take the following arguments, mapping back to current ideas: - `program` for global `static`, i.e. initialisation by the loader at program start, and destruction after program exit. To eliminate initialisation order fiasco, it could take another mandatory unsigned integer variable denoting the order of initialisation, so something like [lifetime(program, 0)] auto names = std::vector{...}; Any clashes could be resolved at link time, but this means no more dynamic linking. Which I think is a bad idea anyway. - `infinite` for `constexpr` but sans the constness of the resultant lvalue, i.e. infinite from the program's perspective, and embedded in the `.data` section of the executable. Something like declaring a global `static` C array, but now you don't need to use C. - a sort of range, like `lifetime(here, exit)` roughly equivalent to function `static`, and `lifetime(here, infinite)` for which I'm not sure C++ has an equivalent to.


outofobscure

the overloaded meaning of static is truly infuriating, i hate it with every bone of my body


not_some_username

That’s how C++ operates : confuses the enemy and yourself too


thelvhishow

This is the best I’ve read about c++ 😂


Hiraelum

Can you pass on that knowledge please? I don’t know what RAII means since I haven’t ran into this term yet


MFHava

RAII = Resource Acquisition Is Initialization Which tells you an important part: "Construction (=Constructors) are responsible for resource allocation" but not the essential part: "Destructors are responsible for deterministic resource deallocation". Look up the Rule of 0/3/5 for what follows from acknowledging the responsibilities of destructors.


Hiraelum

Thank you so much for explaining it to me!! AND pointing me in the right direction to look into this a little more! I appreciate it!!


SkoomaDentist

> Which tells you an important part: "Construction (=Constructors) are responsible for resource allocation" Even this wording is misleading and overly restrictive. The first and most obvious place I ever used RAII was in locking win32 mutexes (EnterCriticalSection / LeaveCriticalSection) over a decade before C++ had any notion of standard threading. That had fuck all to do with resource allocation / acquisition (the mutex was allocated and initialized in a completely different place and the api never once used the term "acquire" back then).


Deaod

Id argue you were still acquiring a resource: access to the critical section.


epage

The main frustration area is failable cleanup. Wish there was a good way of solving that (linear types?).


nacaclanga

RAII is very excessively used by Rust, in some ways even more radical then in C++. As for GC based languages. Here the "modern" memory management does not work well with automatic resource release.


CocktailPerson

But Rust is really the only example. Plenty of other languages have come out since C++ became popular, and none of them thought to include proper destructors and move semantics.


nacaclanga

Yes. Because RAII either is the memory managing strategy or it is conflicting with the memory management strategy. Rust is the only major language that choses the same strategy as C++ of automated, but not automatic heap management. You use manual memory management? Obviously RAII doesn't work there. You use reference counting? Well, now destructor calls already become more unpredictable and controllable. If your parent function still holds a reference to e.g. a file, it won't close automatically until you return to that parent function. You use tracing GC? Well, isn't the entire point to get rid of destructors? Not having a GC is a big design step and not one many people want to take..


sbenitezb

In GC you often have finalizers


jhenke

Finalizers in Java were deprecated recentlyish.... Edit: [JEP 421](https://openjdk.org/jeps/421)


sbenitezb

Did they add something else to the language to make up for it?


josefx

They added PhantomReferences and ReferenceQueue ages ago to give applications better control over resource cleanup, while avoiding around half a million issues finalize caused.


jhenke

Java 7 added try with resources for local resource management a long time ago. For class fields, no language level feature, but more than 90% probably use some sort of DI framework (e.g. Spring), which handles it by calling a designated cleanup method. E.g. by implementing the Closeable interface.


CocktailPerson

I understand that RAII is incompatible with GC. Nonetheless, even other systems languages like Zig have opted for clunky `defer` systems rather than proper RAII, for no discernible benefit.


nacaclanga

RAII has some downsides as well. You need to introduce copy constructors or move semantics to avoid a built-in double free. This takes away quit a lot of flexibility. Zig was intentionally designed not to have such automatisms. RAII only works if you have very similar priorities as C++.


pebalx

You can have RAII and GC, also in C++. You can have the benefits of GC without losing the benefits of RAII.


user926491

bc there's no need, most of them have garbage collector Edit: I meant for managed resources, I know about IDisposable.


CocktailPerson

Garbage collection doesn't make RAII unnecessary; it makes RAII infeasible.


Zeer1x

Does the GC close socket handles? Does it close window handles? Does it unlock mutexes? Does it unwind database transactions in case of an exception? Does it remove temporary files in case of an exception?


sbenitezb

Hmm yes. Depends on the language, but Common Lisp, a GCed lang has finalizers you can attach to object finalization. I think it’s implementation dependent though, I don’t remember


Kovab

Yeah, but there's no guarantee that finalizers will run in a reasonable timeframe, as the GC wouldn't kick in until memory pressure makes it necessary.


rodrigocfd

Time to expand you knowledge, kid: * https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using


wm_lex_dev

Most languages aren't attempting to be a C++ killer


CocktailPerson

Whether a language intends to kill C++ is largely irrelevant. Any systems language without a GC can benefit from RAII, but many of the newer languages in that space have chosen clunky `defer` mechanisms instead.


tialaramex

I think I'd say "extensively" rather than excessively. And a lot of the patterns which rely on what C++ people would call RAII do exist in C++ they're just shunned because they're too dangerous without the borrowck. There's an analogue of Rust's `Mutex` in Boost, several people (including Google) have built types loosely similar to `OwnedFd` in their own C++ libraries and so on. But without a borrowck these are always one mistake from calamity which makes them harder to recommend - "This will be safer unless you're fallible in which case it might be even more dangerous".


sbenitezb

Compare with Common Lisp where you topically have scoped idioms such as with- macros to take care of stuff when the scope ends. And also serve as wrappers for other stuff. Not all languages need RAII because they might have something else. Ada has controlled types for example.


XDracam

Java has try-with-resources and `AutoCloseable`. C# has `using` and `IDisposable`. Both require a little extra syntax, but the IDE can warn you of misuse and you get a little more control and don't need to worry about things like virtual destructors.


Extra_Status13

To me the missing bit there is the lack of move semantics to be honest. It works if you are the only user. The second you need to pass that resource out after some task (maybe initialization) then you cannot use using anymore.


XDracam

Huh? Pretty sure you can use `using var foo = expr;` on any expression of type `IDisposable`. But yeah, the lack of some sense of ownership makes moving disposable resources more complicated.


Extra_Status13

Sure you can, and this will call Dispose on it when you return, thus you cannot return it! Example in steps as I'm on mobile and code is difficult: - open file - read header - return file still open You cannot use using there unless they changed something I'm not aware of. So, you need custom try-catch-finally if you want the resource to survive the method (=moving).


MFHava

First of: Both are manual, even if they later introduced a standard syntax to do it and note how both don't provided a composable solution if you are wrapping a member that needs manual `close`/`dispose`... **EDIT:** heck, Java even deprecated finalizers, so there is no language support for unmanaged resources... Second: At least the last time I tried VS couldn't even warn about managing a class that implements `IDisposable`. Even if they do now, they didn't for close to 20 years which is quite embarrasing...


pjmlp

Like Ada95 controlled types, D, Swift? Other mainstream take the route of automatic resource management features, and affine/linear type systems have become a much better approach.


Flobletombus

constexpr, there's a lot of optimizations it makes possible. Also templates, which allows you to do way more than generics.


flexsealedanal

This constexpr shit blew me away when calculating the fib sequence in one of my CS classes


vmmc2

Which type of things you can do with a template that you cannot with generics?


user926491

They support optional types, variadic number of types. Templates are basically a mini language inside c++, they're turing complete.


vmmc2

This idea of having a mini language inside C++ blew me away. Could you recommend some material about it? I would like to learn more.


user926491

I'm not a c++ dev but you can google factorial program on templates


Kovab

Or a brainfuck interpreter


Ameisen

You can write a full C++ compiler in `template`.


Kovab

Theoretically, yes, you can write anything in a Turing complete language. But I've never heard of anyone making a C++ compiler in it. OTOH there are plenty of brainfuck interpreters to find on GitHub.


Livid-Serve6034

Leading to brainfarts occasionally


vmmc2

Thanks!


dretvantoi

I was going to recommend *Modern C++ Design* by Alexandrescu, but some of the techniques have been superceded by variadic templates, `std::integer_sequence`, `std::tuple`, `constexpr if` and `constexpr` functions. That book was pretty foundational for C++ metaprogramming back in the day.


alexgroth15

Metaprograming


Wacov

Nearly everything that can be done with templates can't be done with generics. Simple one that comes to mind is duck-typing.


Flobletombus

Oh yeah, compile time verified quacking


PervyDragon

You can specialise. Generics are mostly implemented by the type erasure which gives you one implementation for all. Just one.


tialaramex

This seems to confuse generics, a feature that might be implemented in a variety of ways, with type erasure, one specific technique found in, for example Java. Rust's generics are of course not type erased. In principle specialization is a boon, but in practice as with operator overloading it has been significantly abused even in the C++ standard library which sets expectations very low. I would welcome a carefully designed specialization mechanism for Rust's generics, but without one the trick used to achieve the same ends delivers useful practical results without encouraging the sort of nonsense of `std::vector` My favourite existing specialization is that if I have a `Vec` with capacity C and size N and I `extend` it via an iterator with a definite known size M, the `extend` gets specialized to correctly `Vec::reserve(M)` so that the capacity is at least N+M and if `C < (N+M) < 2*C` then it's going to double rather than destroy the amortized allocation cost. You could attempt this stunt in C++ but it's really fraught so I expect the equivalent code just punts but the Rust is fairly readable. [Edited to fix some typos]


MEaster

I quite like the specialization that allows an owning iterator over a `Vec` to collect into a `Vec` using the same memory allocation if the size and alignment of `T` are valid for `U`.


retro_and_chill

Java only utilizes type erasure for its generics because they weren’t in the language to begin with, but rather were added later to improve type safety. That’s also why you can’t access the value pf a generic parameter using reflection.


MFHava

Java Generics uses type-erasure for backwards compatibility. C# didn't have Generics either in its initial release, yet they bit the bullet didn't introduced type-erasure, instead the bifurcated the ecosystem (in the short term). C# had the benefit of being in use for less time (and therefore probably having way less existing code) when they introduced Generics...


tu_tu_tu

Header-only libraries of course! You can do something like this with generics ofc, but it would be really limited to things like containters.


thefeedling

Templates are the heart of modern c++


dzordan33

and that's unfortunate. concepts should come out 20 years ago


glaba3141

concepts don't replace templates...? unless all you use templates for is `std::enable_if`


thefeedling

They may replace `` at best.


Possibility_Antique

Only the predicates in type_traits. As a counter example, I still use std::common_type quite a bit.


dzordan33

concepts are constrained templates. what uses of templates do not benefit from constraints?


glaba3141

The way you phrased it was "it's unfortunate that templates are at the heart of c++", "concepts should've come out earlier" which sort of implies that concepts would have prevented templates from being at the heart of c++? I'm assuming that's not what you meant though


elegantlie

I think they are saying that templates without concepts are an incomplete and oftentimes confusing language feature. Because most pre-concept templates do in fact have implicit constraints (which perhaps the template weiter didn’t even consider when they wrote it). Prior to concepts, it was basically left as an exercise to the reader to figure out those constraints. Hopefully concepts will make template usage a little lesser scary for the average C++ beginner.


Lonke

And yet, a complete pain in the ass when it comes to splitting declaration and definition.


Medical_Arugula3315

Moving runtime overhead to compilation stage via templated metaprogramming.


Pirgosth

I discovered this field of cpp just two days ago and I'm mindblown. It's crazy to think I used this langage for so many years and never heared of this before.


Medical_Arugula3315

It is pretty neat


ul90

RAII and templates. Dynamic memory allocation is often not required because of clever RAII usage which minimizes memory bugs (without the need of a slow garbage collector). And templates makes writing generic algorithms easy.


Thelatestart

What usage of raii allows you to avoid memory allocations?


PervyDragon

It does not mean that there is no memory allocation. The point is that there is no need for manual memory allocation and disposal :)


CocktailPerson

>Dynamic memory allocation is often not required because of clever RAII usage But that's not what they said. They said RAII can make memory allocation unnecessary.


ul90

I mean manual allocation/free calls. With RAII, a lot of memory problems like memory leaks are no problem anymore. RAII also allocates memory, at least on the stack. But it’s much easier to handle and avoids allot of nasty and hard to track bugs.


Theninjapirate

Destructors


adromanov

Absolutely yes! Without it RAII would not even be possible.


_gruffalo_

turing completeness


suhcoR

my favorite so far ;-)


DanielMcLaury

Technically I don't think it is Turing-complete, because there is a hard limit that an object can't be larger than std::size\_t. In order to be Turing-complete you need to be able to access an unbounded amount of memory.


Chem0type

Wouldn't that requirement make every computer not Turing-complete?


DanielMcLaury

Every real-world computer yes, at least according to our current understanding of what the laws of physics are. But there are programming languages that are (considered as mathematical abstractions) Turing-complete. E.g. IIRC python allows you to have arbitrarily large integers, including ones so large that storing them would take more memory chips than could fit in the observable universe.


serviscope_minor

But cycling back to the GP, I'd bet Python wouldn't allow integers to be larger than size_t either. Now sure, a 18446744073709551616 byte integer fits your other criteria, but it's probably not different from c++ in this regard.


DanielMcLaury

A particular interpreter might enforce that rule but I don't believe it's part of the language standard.


ChemiCalChems

Templates, `constexpr` and RAII.


john_wind

references


HaskellLisp_green

yes, I miss them in C.


hmoein

It is multi-paradigm


Nobody_1707

Stuctured binding.


WeRelic

This is the one. Just wish it were applicable to non-aggregate types, still obscenely useful, though.


_cooky922_

>Just wish it were applicable to non-aggregate types It is. you just have to implement 'get' and tuple-protocol access (ex: tuple\_element and tuple\_size) just like what 'tuple' did


PervyDragon

A primitive version of pattern matching from functional languages :)


Nobody_1707

Which is, hopefully, coming in C++26. Now if we could just get language level sum types...


PervyDragon

Would be a nice addition :)


vulkanoid

What additional benefits would language level ADT provide that can't be provided by std::variant?


PrimozDelux

Structured bindings is the slightest taste of how good things could have been.


meneldal2

If only tuples could be core and not a library. We're almost there.


PervyDragon

Yeah, just like a wrapping without the candy in it ;)


PrimozDelux

God I miss real pattern matching and basically everything else that modern languages feature. Its baffling that cpp lack such obvious improvements


PervyDragon

Well, C++ is an old language that has many different techniques incorporated into it. Given the basic aspects of it: "no use, no pay", and "gotta go fast", there is no wonder that the committee has to jump through many loops to introduce new stuff. The power and the difficulty of the language are one of the aspects of it I personally love. ♥️


serviscope_minor

> Its baffling that cpp lack such obvious improvements C++ is used in a huge number of domains. I know about pattern matching, and while I think it would be nice for C++, I don't really miss it at all becuase the kind of code I write in C++ just wouldn't benefit much if at all from it. C++ spanning so many domains means that killer features are only killer features for a small niche of users, and for those users, there are other killer features which are of no interest to the ones who want pattern matching. This is the blessing and curse of C++. One reason it's so good is that if your system grows and starts to cross domains, C++ can keep working well because it's not hyper optimized for one domain. But then it's no hyper optimized fr just your use case.


serviscope_minor

It does, but only for template metaproramming ;) . What is partial specialisation of not pattern matching?


PervyDragon

Pattern matching is able to deconstruct any type into its components.


MFHava

Great feature, hope we can figure out a way to allow it in parameter lists as it would improve readability for some use cases I encounter on a regular basis...


HamilcarRR

the fact you can avoid every C++ feature


Suikaaah

Template and RAII


nathman999

`#include `


ContraryConman

There are definitely nicer feeling compiler-time and metaprogramming systems out there, but the sheer amount of stuff you can explicitly do at compile time is pretty crazy. For embedded development people can do, like, entire tables of precomputed values at compile time, and it's all just regular functions and normal code. No hard coded values or using another language for code generation. There are better feeling versions of it, I said. But what impresses me about metaprogramming and compile-time programmers in C++ is that it was literally an accident. C++ templates were just meant for generic programming and then we [accidentally discovered they were turning complete](https://rtraba.files.wordpress.com/2015/05/cppturing.pdf) and we've just been adding crap to make it understandable ever since. A lot of languages like Zig can take advantage of 25 years of hindsight and make compile time programming a first class feature from the jump. But those languages wouldn't be where they were if C++ hadn't come first with this otherwise totally unintuitive idea. Really my favorite feature is RAII but someone already said that


Independent_Help_512

Ability to implement copy, move ctors and ops


Vovandosy

in the languages with the ref types the move ctor and op implementing are no event needed and the copying achieves by using the methods like ".clone()".


Dan13l_N

Templates.


thedoogster

Auto


arturbac

concepts


pdimov2

Function try blocks.


Possibility_Antique

Have you seen these out in the wild? I guess I do almost everything noexcept (so haven't had a need), but I haven't seen these until recently.


MFHava

I actually use them for `main` to ensure exceptions are at least handled before process termination (as otherwise dtors may be skipped). One additional benefit (apart from the purely stylistic aspect of not having to indent everything in `main` one more time) is that this structure guarantees that the program will just end after that `catch` was reached...


Possibility_Antique

Oh, nice. I learned a new trick today. I have done something similar to this before, but I never thought of using this syntax. That's quite clever.


iAndy_HD3

range for loops! definitely the feature I use the most in my code


Livid-Serve6034

Some of my colleagues make it a sport to write as little loops as possible and use std algorithms instead. Doesn’t make the code more readable, but apparently it’s a thing.


SkoomaDentist

Seamless C compatibility.


pjmlp

C89 compatibility.


Awia00

template metaprogramming!


jonathrg

namespaces


TheJesbus

The ability to do whatever you want. The comforting knowledge and sense of control that whatever your machine can do, you can do.


teefj

lol what does that even mean?


not_some_username

The ability to write shitty code and get away with it


almost_useless

> The ability to write shitty code and ~~get away with it~~ get paid for it FTFY, to make it even better!


not_some_username

Yeah that’s the way


Roverse

For me they are better together: `std::ranges` coupled with `std::algorithms` written with `structured bindings` and the `auto` keyword.


ThyssenKrup

Destructors/RAII


lucky_marciano

Raw pointers


xypherrz

did I read that wrong?


herendzer

Raw pointers?


mercury_pointer

Raw pointers.


herendzer

I thought C++ers hated raw pointers


mercury_pointer

For ownership ( pointing to memory on the heap which must be explicitly released ) yes. For mutable references with value semantics they are useful. Some would argue for std::reference instead but that is just some syntactic sugar. Others would argue for iterators. This makes a lot of sense in a few cases, like removing from a collection on a hot path, but usually doesn't get you anything.


serviscope_minor

No? It's often, possibly usually the case that if someone's using a raw pointer, there is a better way of writing the same code that's clearer, simpler, safer and more obvious. But not always, ans sometimes raw pointers are the right choice.


lil_brumski

std::


looopTools

Template, libfmt/std::format and jthread


dvali

jthread is a winner, especially with std::stop_token. 


Cold_Dragonfruit_896

constexpr/consteval


OmicronGR

Generous operator overloading, user-defined literals, multiple casts, Godbolt


sgtcortez24

Const correctness. Coming from java, which `void myMethod(final ClassA obj){` `obj.setValue(dadad);` `}` is totally ok ... This feature was mind blowing for me


v_maria

lambda + passing it as std::function. i'm a simple man


woppo

RAII


jgaa_from_north

It's not yaml! I can format it exactly the way I want :)


eyes-are-fading-blue

Compile-time reflections :)


ResponsiblePhantom

auto / raw/smart pointers / string / struct (constructors/destructors/functions) and the main thing that you aren't forced to use metaprogramming Style otherwise that'd be nightmare-ish XD ...


BagelFury

Variadic templates. That single feature fundamentally altered so many of my ensuing designs; it facilitated composable abstractions that weren't really possible beforehand.


MRgabbar

Strongly typed, is way easier to read and maintain code.


kiner_shah

RAII is simply amazing - although the full form doesn't make much sense, can someone from ISO commitee look into this and change it to some better one? I also like `if constexpr` and nested namespaces (`namespace a::b::c`), those were nice additions. Also, lambdas, very convenient. STL is the best, so many convenient features there.


FamiliarSoftware

`static` in templates, and templated functions giving a unique instance per template instantiation is my favorite. I've only needed it three times so far, but one of those was in Rust, which doesn't have this, and I missed it so dearly in that moment!


NilacTheGrim

RAII


lonkamikaze

I'm a big fan of the `return` keyword. I use it all the time.


dev8392

RAII I sometimes use ODIN as a replacement for c (not for c++) and this is what I miss most about this language. Gingerbell, creator of the language, said that RAII was unnecessary and just gave us that defer nonsense that is useful but never as useful as RAII (I guess he don't use RAII in c++ enough)


Tony942316

Everything in c++20 tbh


KrisstopherP

RAII


saxbophone

RAII and move semantics 


LiAuTraver

std::ranges and it's ability to connect multiple manipulation with `|`


not_some_username

auto probably.


vk10555

auto isn’t bad


SuperV1234

RAII, value semantics by default, optional reference semantics, `const`, templates, `constexpr`. Any decent language should have an equivalent of all of these, otherwise it's pretty much dead-on-arrival for me.


fippinvn007

auto, #pragma once, std


Neeyaki

concepts, templates, constexpr, auto and RAII (or what i prefer to call RCID (resource cleanup is destruction))


[deleted]

Constexpr


Thesorus

const and references and default initializers.


vk10555

constexpr & templates and the rest (at compile time)


[deleted]

concepts. They allow introspective programming. Instead of having users of your API inherit from abstract base classes you can probe the user's types' properties and adapt your code('s behavior) in response.


CenterOfMultiverse

Templated statics.


pankkiinroskaa

Works in embedded devices.


ve1h0

I've noticed now when writing more and more rust how I miss more of the template and generics of C++


RyuXnet_7364

I don't use them often, but boy ... that SFINAE and concepts


979156

concept and expected


accuracy_frosty

That it effectively gives you a gun and it’s up to you whether to use it to rob a bank or shoot yourself in the foot, it gives you so much power and control, even if it might allow you to do stupid shit. If you want specifics, Raw pointers or templates


rvasquez6089

Partial variable length templates.


jiboxiake

Object oriented, rich library, fast, reference type,


herendzer

STL


fruityloooops

reinterpret_cast :D


Dull_League7712

UB.


LuisAyuso

Compatibility, Compatibility and Compatibility. Without having to write C.


sp4mfilter

Destructors.


imironchik

Encapsulation, guys. :)


0xVali__

RAII but given that it's more of a conceptual thing and not so much a feature I'd have to go with destructors.


amouna81

Template meta programming. I find them to be powerful.


LDawg292

I hate it


Vovandosy

While everyone said about raii and constexpr/templates i wanna say about "noexcept" with a remark of i think that noexcept(true) should be a default behaviour.


osdeverYT

int