frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Female Asian Elephant Calf Born at the Smithsonian National Zoo

https://www.si.edu/newsdesk/releases/female-asian-elephant-calf-born-smithsonians-national-zoo-an...
1•gmays•34s ago•0 comments

Show HN: Zest – A hands-on simulator for Staff+ system design scenarios

https://staff-engineering-simulator-880284904082.us-west1.run.app/
1•chanip0114•1m ago•0 comments

Show HN: DeSync – Decentralized Economic Realm with Blockchain-Based Governance

https://github.com/MelzLabs/DeSync
1•0xUnavailable•6m ago•0 comments

Automatic Programming Returns

https://cyber-omelette.com/posts/the-abstraction-rises.html
1•benrules2•9m ago•1 comments

Why Are There Still So Many Jobs? The History and Future of Workplace Automation [pdf]

https://economics.mit.edu/sites/default/files/inline-files/Why%20Are%20there%20Still%20So%20Many%...
2•oidar•12m ago•0 comments

The Search Engine Map

https://www.searchenginemap.com
1•cratermoon•19m ago•0 comments

Show HN: Souls.directory – SOUL.md templates for AI agent personalities

https://souls.directory
1•thedaviddias•20m ago•0 comments

Real-Time ETL for Enterprise-Grade Data Integration

https://tabsdata.com
1•teleforce•23m ago•0 comments

Economics Puzzle Leads to a New Understanding of a Fundamental Law of Physics

https://www.caltech.edu/about/news/economics-puzzle-leads-to-a-new-understanding-of-a-fundamental...
2•geox•24m ago•0 comments

Switzerland's Extraordinary Medieval Library

https://www.bbc.com/travel/article/20260202-inside-switzerlands-extraordinary-medieval-library
2•bookmtn•25m ago•0 comments

A new comet was just discovered. Will it be visible in broad daylight?

https://phys.org/news/2026-02-comet-visible-broad-daylight.html
2•bookmtn•29m ago•0 comments

ESR: Comes the news that Anthropic has vibecoded a C compiler

https://twitter.com/esrtweet/status/2019562859978539342
1•tjr•31m ago•0 comments

Frisco residents divided over H-1B visas, 'Indian takeover' at council meeting

https://www.dallasnews.com/news/politics/2026/02/04/frisco-residents-divided-over-h-1b-visas-indi...
1•alephnerd•31m ago•0 comments

If CNN Covered Star Wars

https://www.youtube.com/watch?v=vArJg_SU4Lc
1•keepamovin•37m ago•0 comments

Show HN: I built the first tool to configure VPSs without commands

https://the-ultimate-tool-for-configuring-vps.wiar8.com/
2•Wiar8•40m ago•3 comments

AI agents from 4 labs predicting the Super Bowl via prediction market

https://agoramarket.ai/
1•kevinswint•45m ago•1 comments

EU bans infinite scroll and autoplay in TikTok case

https://twitter.com/HennaVirkkunen/status/2019730270279356658
5•miohtama•48m ago•3 comments

Benchmarking how well LLMs can play FizzBuzz

https://huggingface.co/spaces/venkatasg/fizzbuzz-bench
1•_venkatasg•51m ago•1 comments

Why I Joined OpenAI

https://www.brendangregg.com/blog/2026-02-07/why-i-joined-openai.html
19•SerCe•51m ago•11 comments

Octave GTM MCP Server

https://docs.octavehq.com/mcp/overview
1•connor11528•52m ago•0 comments

Show HN: Portview what's on your ports (diagnostic-first, single binary, Linux)

https://github.com/Mapika/portview
3•Mapika•54m ago•0 comments

Voyager CEO says space data center cooling problem still needs to be solved

https://www.cnbc.com/2026/02/05/amazon-amzn-q4-earnings-report-2025.html
1•belter•58m ago•0 comments

Boilerplate Tax – Ranking popular programming languages by density

https://boyter.org/posts/boilerplate-tax-ranking-popular-languages-by-density/
1•nnx•58m ago•0 comments

Zen: A Browser You Can Love

https://joeblu.com/blog/2026_02_zen-a-browser-you-can-love/
1•joeblubaugh•1h ago•0 comments

My GPT-5.3-Codex Review: Full Autonomy Has Arrived

https://shumer.dev/gpt53-codex-review
2•gfortaine•1h ago•0 comments

Show HN: FastLog: 1.4 GB/s text file analyzer with AVX2 SIMD

https://github.com/AGDNoob/FastLog
2•AGDNoob•1h ago•1 comments

God said it (song lyrics) [pdf]

https://www.lpmbc.org/UserFiles/Ministries/AVoices/Docs/Lyrics/God_Said_It.pdf
1•marysminefnuf•1h ago•0 comments

I left Linus Tech Tips [video]

https://www.youtube.com/watch?v=gqVxgcKQO2E
1•ksec•1h ago•0 comments

Program Theory

https://zenodo.org/records/18512279
1•Anonymus12233•1h ago•0 comments

Show HN: Local DNA analysis skill for OpenClaw

https://github.com/wkyleg/personal-genomics
2•wkyleg•1h ago•0 comments
Open in hackernews

How well do you know C++ auto type deduction?

https://www.volatileint.dev/posts/auto-type-deduction-gauntlet/
91•volatileint•1mo ago

Comments

CalChris•1mo ago
Apparently the C++ standard calls this type deduction. But I've always called it type inference.
plq•1mo ago
Type inference is when you try to infer a type from its usage. ``auto`` does no such thing, it just copies a known type from source to target. Target has no influence over source's type.

https://news.ycombinator.com/item?id=11604474

Maxatar•1mo ago
Type deduction is a form of type inference, a very restricted/crude form of type inference that only considers the type of the immediate expression. The term is used in C++ because it predates the use of auto and was the term used to determine how to implicitly instantiate templates. auto uses exactly the same rules (with 1 single exception) as template type deduction, so the name was kept for familiarity. If instead of initializing a variable, you went through the examples on this website and passed the expression into a template function, the type would be deduced in exactly the same way with the exception of initializer lists.

Type inference is usually reserved for more general algorithms that can inspect not only how a variable is initialized, but how the variable used, such as what functions it's passed into, etc...

zarzavat•1mo ago
> Type inference is usually reserved for more general algorithms that can inspect not only how a variable is initialized, but how the variable used, such as what functions it's passed into, etc...

In a modern context, both would be called "type inference" because unidirectional type inference is quite a bit more common now than the bidirectional kind, given that many major languages adopted it.

If you want to specify constraint-based type inference then you can say global HM (e.g. Haskell), local HM (e.g. Rust), or just bidirectional type inference.

jb1991•1mo ago
The same general concepts often have different terminology between different languages. For example, which is better, a parent class or a super class? Or a method function or a member function? Initializer or constructor? Long list of these synonyms.
gpderetta•1mo ago
Inference is a constraint solving problem: the type of a variable depends on all the ways it is used. In C++, deduction simply sets the type of a variable from its initializing expression.

95%[1] of the time, deduction is enough, but occasionally you really wish you had proper inference.

[1] percentage made up on the spot.

112233•1mo ago
Saving this to use as an argument when C++ comes up in a discussion. This toxic swamp cannot be fixed and anyone chosing to jump into it needs a warning.
OneDeuxTriSeiGo•1mo ago
Most of the relevance of this is limited to C++ library authors doing metaprogramming.

Most of the "ugly" of these examples only really matters for library authors and even then most of the time you'd be hard pressed to put yourself in these situations. Otherwise it "just works".

Basically any adherence to a modicum of best practices avoids the bulk of the warts that come with type deduction or at worst reduces them to a compile error.

112233•1mo ago
I see this argument often. It is valid right until you get first multipage error message from a code that uses stl (which is all c++ code, because it is impossible to use c++ without standard library).
wheybags•1mo ago
And I see this argument often. People make too much fuss about the massive error messages. Just ignore everything but the first 10 lines and 99.9% of the time, the issue is obvious. People really exaggerate the amout of time and effort you spend dealing with these error messages. They look dramatic so they're very memeable, but it's really not a big deal. The percentage of hours I've spent deciphering difficult cpp error messages in my career is a rounding error.
1718627440•1mo ago
> it is impossible to use c++ without standard library

Citation needed. This is common for embedded application, since why would anyone program a STL for that?

OneDeuxTriSeiGo•1mo ago
There's actually multiple standard libraries for embedded applications and a lot of the standard library from C++11 and on was designed with embedded in mind in particular.

And with each std release the particularly nasty parts of std get decoupled from the rest of the library. So it's at the point nowadays where you can use all the commonly used parts of std in an embedded environment. So that means you get all your containers, iterators, ranges, views, smart/RAII pointers, smart/RAII concurrency primitives. And on the bleeding edge you can even get coroutines, generators, green threads, etc in an embedded environment with "pay for what you use" overhead. Intel has been pushing embedded stdlib really hard over the past few years and both they and Nvidia have been spearheading the senders and receivers concurrency effort. Intel uses S&R internally for handling concurrency in their embedded environments internal to the CPU and elsewhere in their hardware.

(Also fun side note but STL doesn't "really" stand for "standard template library". Some projects have retroactively decided to refer to it as that but that's not where the term STL comes from. STL stands for the Adobe "Software Technology Lab" where Stepanov's STL project was formed and the project prior to being proposed to committee was named after the lab.)

gpderetta•1mo ago
AFAIK Stepanov only joined Adobe much later. I think he was at HP during the development of the STL, but moved to SGI shortly after (possibly during standardization).

The other apocryphal derivation of STL I have heard is "STepanov and Lee".

OneDeuxTriSeiGo•1mo ago
AFAIK He started work on the STL at HP and then SGI based on his and Musser's work on Generic Programming but it didn't get the name STL until he was at the STL.

This of course coming from Sean Parent who was and afaik still is quite close with Stepanov. Sean Parent of course being famous in his own right but also being notable for bringing Stepanov to Adobe and being the one to push for Stepanov to propose the STL to WG21 (the C++ ISO Std committee).

112233•1mo ago
gladly! Since deep-linking draft pdf from phone is hard, here is the next best thing: https://en.cppreference.com/w/cpp/freestanding.html

freestanding requires almost all std library. Please note that -fno-rtti and -fno-exceptions are non-conformant, c++ standard does not permit either.

Also, such std:: members as initializer_list, type_info etc are directly baked into compiler and stuff in header must exactly match internals — making std library a part of compiler implementation

1718627440•1mo ago
> Please note that -fno-rtti and -fno-exceptions are non-conformant, c++ standard does not permit either.

I did not know that.

My understanding was that C does not require standard library functions to be present in freestanding. The Linux kernel famously does not build in freestanding mode, since then GCC can't reason about the standard library functions which they want. This means that they need to implement stuff like memcpy and pass -fno-builtin.

Does that mean that freestanding C++ requires the C++ standard library, but not the C standard library? How does that work?

112233•1mo ago
Honestly? No idea how the committee is thinking. When, say, gamedev people write proposal, ask for a feature, explain it is important and something they depend on and so on, it gets shot down on technicality. Then they turn around and produce some insane feature that, like, rips everything east to west (like modules), and suddenly voting goes positive.

The "abstract machine" C++ assumes in the standard is itself a deeply puzzling construct. Luckily, compiler authors seem much more pragmatic and reasonable, I do not fear -fno-exceptions dissapearing suddenly, or code that accesses mmapped data becoming invalid because it didn't use start_lifetime_as

1718627440•1mo ago
So as to your understanding

> freestanding C++ requires the C++ standard library, but not the C standard library

is true?

> The "abstract machine" C++ assumes in the standard is itself a deeply puzzling construct.

I find the abstract machine to be quite a neat abstraction, but I am also more of a C guy.

112233•1mo ago
Looking here:

https://eel.is/c++draft/compliance

One of required headers in freestanding, <cstdlib>, is labelled "C standard library", but it is not <stdlib.h> Something similar with other <csomething> headers.

This kinda implies C library is required, if I read it correctly, but maybe someone else can correct me: https://eel.is/c++draft/library.c

1718627440•1mo ago
So from the GCC 10 documentation:

> The ISO C standard defines (in clause 4) two classes of conforming implementation. A "conforming hosted implementation" supports the whole standard including all the library facilities; a "conforming freestanding implementation" is only required to provide certain library facilities: those in '<float.h>', '<limits.h>', '<stdarg.h>', and '<stddef.h>'; since AMD1, also those in '<iso646.h>'; since C99, also those in '<stdbool.h>' and '<stdint.h>'; and since C11, also those in '<stdalign.h>' and '<stdnoreturn.h>'. In addition, complex types, added in C99, are not required for freestanding implementations.

> The standard also defines two environments for programs, a "freestanding environment", required of all implementations and which may not have library facilities beyond those required of freestanding implementations, where the handling of program startup and termination are implementation-defined; and a "hosted environment", which is not required, in which all the library facilities are provided and startup is through a function 'int main (void)' or 'int main (int, char *[])'. An OS kernel is an example of a program running in a freestanding environment; a program using the facilities of an operating system is an example of a program running in a hosted environment.

> GCC aims towards being usable as a conforming freestanding implementation, or as the compiler for a conforming hosted implementation. By default, it acts as the compiler for a hosted implementation, defining '__STDC_HOSTED__' as '1' and presuming that when the names of ISO C functions are used, they have the semantics defined in the standard. To make it act as a conforming freestanding implementation for a freestanding environment, use the option '-ffreestanding'; it then defines '__STDC_HOSTED__' to '0' and does not make assumptions about the meanings of function names from the standard library, with exceptions noted below. To build an OS kernel, you may well still need to make your own arrangements for linking and startup. *Note Options Controlling C Dialect: C Dialect Options.

> GCC does not provide the library facilities required only of hosted implementations, nor yet all the facilities required by C99 of freestanding implementations on all platforms. To use the facilities of a hosted environment, you need to find them elsewhere (for example, in the GNU C library). *Note Standard Libraries: Standard Libraries.

> Most of the compiler support routines used by GCC are present in 'libgcc', but there are a few exceptions. GCC requires the freestanding environment provide 'memcpy', 'memmove', 'memset' and 'memcmp'. Finally, if '__builtin_trap' is used, and the target does not implement the 'trap' pattern, then GCC emits a call to 'abort'.

So the last paragraph means that my remark about the Linux kernel might be wrong.

So the required headers are all about basic constants for types, the types themselves (bool), and basic language features like stdarg, iso646 or stdalign. Sounds sensible to me. Not sure what C++ does with that.

This matches with https://en.cppreference.com/w/c/language/conformance.html . Since C23, stdlib.h is also required for dynamic allocation, string conversions and some other things.

This also actually matches the links provided by you. In https://eel.is/c++draft/cstdlib.syn you see that not all declarations are actually marked for freestanding implementations.

gpderetta•1mo ago
> freestanding requires almost all std library.

have you actually read the page you linked to? None of the standard containers is there, nor <iostream> or <algorithm>. <string> is there but marked as partial.

If anything, I would expect more headers like <algorithm>, <span>, <array> etc to be there as they mostly do not require any heap allocation nor exceptions for most of their functionality. And in fact they are available with GCC.

The only bit I'm surprised is that coroutine is there, as they normally allocate, but I guess it has full support for custom allocators, so it can be made to work on freestanding.

OneDeuxTriSeiGo•1mo ago
Those aren't the ugly part of C++ and to be entirely honest reading those messages is not actually hard, it's just a lot of information.

Those errors are essentially the compiler telling you in order:

1. I tried to do this thing and I could not make it work.

2. Here's everything I tried in order and how each attempt failed.

If you read error messages from the top they make way more sense and if reading just the top line error doesn't tell you what's wrong, then reading through the list of resolution/type substitution failures will be insightful. In most cases the first few things it attempted will give you a pretty good idea of what the compiler was trying to do and why it failed.

If the resolution failures are a particularly long list, just ctrl-f/grep to the thing you expected to resolve/type-substitute and the compiler will tell you exactly why the thing you wanted it to use didn't work.

They aren't perfect error messages and the debugging experience of C++ metaprogramming leaves a lot to be desired but it is an order of magnitude better than it ever has been in the past and I'd still take C++ wall-o-error over the extremely over-reductive and limited errors that a lot of compilers in other languages emit (looking at you Java).

ux266478•1mo ago
To be fair to C++, the only languages with actually decently debuggable metaprograms are Lisp and Prolog.

Modern C++ in general is so hostile to debugging I think it's astounding people actually use it.

112233•1mo ago
Most of the time it's as uou say!

But "I tried to do this thing" error is completely useless in helping to find the reason why the compiler didn't do the thing it was expected to do, but instead chose to ignore.

Say, you hit ambiguous overload resolution, and have no idea what actually caused it. Or, conversely, implicit conversion gets hidden, and it helpfully prints all 999 operator << overloads. Or there is a bug in consteval bool type predicate, requires clause fails, and compiler helpfully dumps list of functions that have differet arguments.

How do you debug consteval, if you cannot put printf in it?

Not everyone can use clang or even latest gcc in their project, or work in a familiar codebase.

OneDeuxTriSeiGo•1mo ago
> How do you debug consteval, if you cannot put printf in it?

This will be massively improved in the next std release hopefully since Compile Time Reflection looks like it's finally shipping.

And of course there exist special constexpr debuggers but more generally you really should be validating consteval code with good test suites ahead of time and developing your code such that useful information is exposed via a public (even if internal) interface.

And of course in the worst case throws function as decent consteval printf even if the UX isn't great.

But of course there's more work on improving this in the future. There's a technique I saw demoed at one of the conferences this year that lets you expose full traces in failure modes for both consteval and non-const async code and it seems like it'll be a boon for debugging.

----

> Not everyone can use clang or even latest gcc in their project, or work in a familiar codebase.

Sure note everyone is that lucky but it's increasingly common. AFAIK TI moved entirely to clang based toolchains a few years back and Microchip has done the same. The old guard are finally picking up and moving to modular toolchain architectures to reduce maintenance load and that comes with upstream std support.

flakes•1mo ago
Auto has really made c++ unapproachable to me. It's hard enough to reason about anything templated, and now I frequently see code where every method returns auto. How is any one supposed to do a code review without loading the patch into their IDE?
themafia•1mo ago
The pain of lisp without any of the joy.
OneDeuxTriSeiGo•1mo ago
I'd suppose this really depends on how you are developing your codebase but most code should probably be using a trailing return type or using an auto (or template) return type with a concept/requires constraint on the return type.

For any seriously templated or metaprogrammed code nowadays a concept/requires is going to make it a lot more obvious what your code is actually doing and give you actually useful errors in the event someone is misusing your code.

jjmarr•1mo ago
I don't understand why anyone would use auto and a trailing return type for their functions. The syntax is annoying and breaks too much precedent.
dataflow•1mo ago
Generally, you don't. I'm not sure why the parent suggested you should normally do this. However, there are occasional specific situations in which it's helpful, and that's when you use it.
OneDeuxTriSeiGo•1mo ago
It just is an improvement for a bunch of reasons.

1. Consistency across the board (places where it's required for metaprogramming, lambdas, etc). And as a nicety it forces function/method names to be aligned instead of having variable character counts for the return type before the names. IMHO it makes skimming code easier.

2. It's required for certain metaprogramming situations and it makes other situations an order of magnitude nicer. Nowadays you can just say `auto foo()` but if you can constrain the type either in that trailing return or in a requires clause, it makes reading code a lot easier.

3. The big one for everyday users is that trailing return type includes a lot of extra name resolution in the scope. So for example if the function is a member function/method, the class scope is automatically included so that you can just write `auto Foo::Bar() -> Baz {}` instead of `Foo::Baz Foo::Bar() {}`.

dataflow•1mo ago
1. You're simply not going to achieve consistency across the board, because even if you dictate this by fiat, your dependencies won't be like this. The issue of the function name being hard to spot is easier to fix with tooling (just tell your editor to color them or make them bold or something). OTOH, it's not so nice to be unable to tell at a glance if the function return type is deduced or not, or what it even is in the first place.

2. It's incredibly rare for it to be required. It's not like 10% of the time, it's more like < 0.1% of the time. Just look at how many functions are in your code and how many of them actually can't be written without a trailing return type. You don't change habits to fit the tiny minority of your code.

3. This is probably the best reason to use it and the most subjective, but still not a particularly compelling argument for doing this everywhere, given how much it diverges from existing practice. And the downside is the scope also includes function parameters, which means people will refer to parameters in the return type much more than warranted, which is decidedly not always a good thing.

rovingeye•1mo ago
Consistency (lambdas, etc.)
Rucadi•1mo ago
it makes function declarations/instantiations much more grep-able.
gpderetta•1mo ago
1) consistency, 2) scoping is different and can make it a significant difference.

I have been programming in C++ for 25 years, so I'm so used to the original syntax that I don't default to auto ... ->, but I will definitely use it when it helps simplify some complex signatures.

Traubenfuchs•1mo ago
Same in Java and Kotlin, but then again, the majority of people who write code wouldn't understand what I mean when I say "whether a collection is returned as List or Set is an important part of the API 'contract'".
dataflow•1mo ago
This makes things seem more complicated than they already are, I feel?

There's nothing special about auto here. It deduces the same type as a template parameter, with the same collapsing rules.

decltype(auto) is a different beast and it's much more confusing. It means, more or less, "preserve the type of the expression, unless given a simple identifier, in which case use the type of the identifier."

jandrewrogers•1mo ago
I knew the answer to most of these intuitively but the story isn’t great. Regardless of the programming language, I’ve always been an “auto” minimalist. There are relatively few contexts where relying on inference is justified by the expedience. Ignoring the issues raises by the article, explicitness simplifies things and reduces bugs.

That said, there are some contexts in which “auto” definitely improves the situation.

jb1991•1mo ago
You will typically find bugs go up when you do not use auto in most average C++ code bases because, as noted by another comment, a lot of C++ developers have the bad habit of writing uninitialized variables, which auto prevents.
adrianN•1mo ago
Automatic conversion between numeric types is also a fun source of bugs.
1718627440•1mo ago
As a C developer to me uninitialized variables are a feature and I love to invoke UB with __builtin_unreachable, because it makes the compiler able to actually bark at me on incorrect usage instead of it silently working.
antonvs•1mo ago
“How well do you know Latin grammar rules?”
wheybags•1mo ago
Romanes eunt domus
Surac•1mo ago
I always try to avoid auto in c++ or var in C#. On the paper it is a nice was to save you from typing out the type but this is only true if you have tool support and can use your mouse to obtain the type. In printouts or even in a text snippet I’m am lost. I think auto inC++ was the try to shorten some overburden type constructs and make it a little more friendly to use heavy templating. Please forgive my bad English. I’m no native speaker
majoe•1mo ago
I came to like auto over the years, although I also use it sparingly. Sometimes the concrete types only add visual noise and not much helpful information, e.g. iterators:

auto it = some_container.begin();

Not even once have I wished to know the actual type of the iterator.

samdoesnothing•1mo ago
Odd, it's not a problem in dynamically typed languages or languages like Kotlin, Swift, etc. I think it's more just what you're used to.
Rucadi•1mo ago
auto has a good perk, it prevents uninitialized values (Which is a source of bugs).

For example:

auto a;

will always fail to compile not matter what flags.

int a;

is valid.

Also it prevents implicit type conversions, what you get as type on auto is the type you put at the right.

That's good.

jb1991•1mo ago
This is indeed exactly correct. Probably on its own this is the most important reason for most people to use it, as I think most of the millions of C++ developers in the world (and yes there are apparently millions) are not messing with compiler flags to get the checks that probably should be there by default anyway. The keyword auto gives you that.
feelamee•1mo ago
uninitialized values are not the source of bugs. This is a good way to find logic errors in code (e.g. using sanitizer)
jb1991•1mo ago
"bug" can refer to many categories of problems, including logic errors. I've certainly seen uninitialized variables be a source of bugs. Stackoverflow for example is full of discussions about debugging problems caused by uninitialized variables, and the word "bug" is very often used in those contexts.

What do you mean it is not a source of bugs?

1718627440•1mo ago
> What do you mean it is not a source of bugs?

I think what they mean, and what I also think is that the bug does not come from the existence of uninitialized variables. It comes from the USE of uninitialized variables. Making the variables initialized does not make the bug go away, at most it silences it. Making the program invalid instead (which is what UB fundamentally is) is way more helpful for making programs have less bugs. That the compiler still emits a program is a defect, although an unfixable one.

As to my knowledge C (and derivatives like C++) is the only common language where the question "Is this a program?" has false positives. It is certainly an interesting choice.

feelamee•1mo ago
I mean that bug is *not in* uninitialized variable - bug in program logic. E.g. one of code pathes don't initialize variable.

So, I see uninitialized variables as a good way to find such logic errors. And, therefore, advice to always initialize variable - bad practice.

Of course if you already have a good value to initialize variable - do it. But if you have no - better leave it uninitialized.

Moreover - this will not cause safety issues in production builds because you can use `-ftrivial-auto-var-init` to initialize automatic variables to e.g. zeroes (`-fhardened` will do this too)

amelius•1mo ago
Maybe an in-between solution could be a tool that substitutes auto in your code.
pjmlp•1mo ago
That is like saying that one rather make fire with sticks and stones than with a lighter, because otherwise one would be lost when going out camping.

IDEs are an invention from the late 1970's, early 1980's.

gpderetta•1mo ago
Very much true. On the other hand web based review interfaces seem to be stuck in the '60, when they could be so much better if they properly integrated with the compiler.
pjmlp•1mo ago
The ones on Github with VSCode (Web) integration look quite good already.
1718627440•1mo ago
I think IDEs are a moving target. Do you consider syntax highlighting to make something an IDE? Macro expansion? Autocomplete? intellisense-like based on full text search? based on a parser? based on the compiler? Is Kate an editor or an IDE? It has LSP support.

Having syntax highlighting makes me slightly faster, but I want to still be able to understand things, when looking at a diff or working over SSH and using cat.

pjmlp•1mo ago
Nope, that is a programmer's editor.
1718627440•1mo ago
I agree, but that means, that even complete integration of the compiler does not make an IDE. So the only distinguishing feature I can think of is startup time /s .
addaon•1mo ago
An IDE, by name, integrates the development environment. Depending on target, development lifecycle usually includes writing code, generating binaries, pushing those binaries to the target, executing on the target, and debugging on the target; so an IDE includes editing, compiling, linking, device/JTAG drivers, and debugging, in my mind. I suppose for platforms without cross-compilation the device drivers vanish, and for languages without compilers and linkers similar; but at a minimum, development means both authoring and debugging code, and so an IDE must provide an integrated view of the debugging process.
1718627440•1mo ago
Then that distinction doesn't match the original claim, that readability of unlabeled code doesn't matter, since we now have IDEs, as this is an orthogonal matter according to your definition.
3836293648•1mo ago
You can rely on IDE features when GitHub's web view has them
xnorswap•1mo ago
The guidelines I follow for C# has "use var where it's obvious, but explicitly type when not".

So for example I'd write:

  var x = new List<Foo>();
Because writing:

  List<Foo> x = new List<Foo>();
Feels very redundant

Whereas I'd write:

  List<Foo> x = FooBarService.GetMyThings();
Because it's not obvious what the type is otherwise ( Some IDEs will overlay hint the type there though ).

Although with newer language features you can also write:

  List<Foo> x = new();
Which is even better.
tcfhgj•1mo ago
I would rename `x` to `foos` and jump to the function/use IDE hints for the exact type when needed.
Aeglaecia•1mo ago
an interesting demarcation of subjective mental encapsulation ... associating the anonymous type of a buffer with the buffer's name ... as opposed to explicitly specifying the type of an anonymously named buffer
Leherenn•1mo ago
Right, although I would argue the most interesting part of the type here is the container, not the containee.

With good naming it should be pretty obvious it's a Foo, and then either you know the type by heart, or will need to look up the definition anyway.

With standard containers, you can have the assumption that everyone knows the type, at least high level. So knowing whether it's a list, a vector, a stack, a map or a multimap, ... is pretty useful and avoid a lookup.

lan321•1mo ago
I usually prefer

    List<Foo> x = new();
since it gives me better alignment and since it's not confused with dynamic.

Nowadays I only use

    var x = new List<Foo>();
in non-merged code as a ghetto TODO if I'm considering base types/interface.
binary132•1mo ago
It’s extremely convenient for certain things. For example, let’s say I’m referring to an enum constant field of a deeply-nested type. This can easily be expressed as “auto k = a.b.c.d.kind” instead of “Alpha::Bet::Charlie::Delta::Kinds k = a.b.c.d.kind”. It should be used sparingly in local contexts where the meaning cannot be confusing.
physicsguy•1mo ago
Auto is fine where the context is obvious, I think. For e.g.:

    void func(std::vector<double> vec) {
        for (auto &v : vec) {
            // do stuff
        }
    }

Here it's obvious that v is of type double.
wheybags•1mo ago
v is double& in your example, not double. But it's not obvious that omitting the & causes a copy. If you see "for (auto v : vec)" looks good right? But if vec contains eg long strings, you've now murdered your perf because you're copying them out of the array instead of grabbing refs. Yes, you could make the same mistake without auto, but it's easier to notice. It's easy to forget (or not notice) that auto will not resolve to a reference in this case, because using a reference is "obviously what I want here", and the name of the feature is "auto" after all - "surely it will figure it out, right?"
spacechild1•1mo ago
> Yes, you could make the same mistake without auto, but it's easier to notice.

Is it really? I rather think that a missing & is easier to spot with "auto" simply because there is less text to parse for the eye.

> If you see "for (auto v : vec)" looks good right?

For me the missing & sticks out like a sore thumb.

> It's easy to forget (or not notice) that auto will not resolve to a reference in this case

Every feature can be misused if the user forgets how it works. I don't think people suddenly forget how "auto" works, given how ubiquitous it is.

tialaramex•1mo ago
It's a foot gun. Why is the default target for this gun my foot? "You should be careful to choose the target properly" isn't an answer to that question.
gpderetta•1mo ago
In what way it is a footgun? auto x = ... ; does what I would expect. Copying is usually the default in C++ and that's what I would expect to happen here.

If auto deduced reference types transparently, it would actually be more dangerous.

spacechild1•1mo ago
That's exactly what I was about to write!
tialaramex•1mo ago
Copying is a weird default because who said that's even achievable, let alone cheap?

So I guess I depart from you there and thus my issue here is not really about auto

spacechild1•1mo ago
C++ has value semantics, which means that values of user-defined types generally behave like values of built-in types. In this sense, copying is the only logical default. It's just how the language has been designed.

Things are different in Rust because of lifetimes and destructive moves. In this context, copying would be a bad default indeed.

> because who said that's even achievable, let alone cheap?

Nobody said that. The thing is that user-defined types can be anything from tiny and cheap to huge and expensive. A language has to pick one default and be consistent. You can complain one way or the other.

1718627440•1mo ago
I find passing by value to be sensible, but the allocating part sounds like a bad idea. Passing the value of something doesn't imply making a copy, if the value is never changed, it can be entirely optimized away.
spacechild1•1mo ago
> Passing the value of something doesn't imply making a copy

Yes, languages like Rust can automatically move variables if the compiler can prove that they will not be used anymore. Unfortunately, this is not possible in C++, so the user has to move explicitly (with std::move).

1718627440•1mo ago
> Unfortunately, this is not possible in C++, so the user has to move explicitly (with std::move).

Honestly why not? A locally used variable sounds to be very much something the compiler can reason about. And a variable only declared in a loop, which is destroyed at the end of each iteration and only read from should be able to be optimized away. I don't know Rust, I mostly write C.

spacechild1•1mo ago
Yes, this could work for simple cases, but this breaks down pretty quickly:

  void checkFoo(const Foo&);
  
  Foo getFoo();
  
  void example() {
    std::vector<Foo> vec;

    Foo foo = getFoo();
    if (checkFoo(foo)) {
      // *We* know that checkFoo() does not store a
      // reference to 'foo' but the compiler does not
      // know this. Therefore it cannot automatically
      // move 'foo' into the std::vector.
      vec.push_back(std::move(foo));
    }
  }
The fundamental problem is that C++ does not track object lifetimes. You would end up with a system where the compiler would move objects only under certain circumstances, which would be very hard to reason about.
1718627440•1mo ago
Ah, you are right. It theoretically should be able to do it, but even with -flto, there are likely cases, where it doesn't. It is less of a problem with C, since you explicitly tell the compiler, whether you want things to get passed as value or pointer. Also I typically annotate ownership, so it it easy to forget that the compiler doesn't actually knows this. This is a weird limitation, there should be just a parameter attribute to do that.
spacechild1•1mo ago
> It theoretically should be able to do it, but even with -flto, there are likely cases, where it doesn't.

Note that link time optimization only works on a particular binary. What if the function is implemented in a shared library?

> It is less of a problem with C, since you explicitly tell the compiler, whether you want things to get passed as value or pointer.

It works the exact same way in C++, though.

1718627440•1mo ago
> What if the function is implemented in a shared library

If it is in the public API/ABI of a shared library, than the calling semantics including lifetime and ownership rules are part of the public interface, so of course the compiler can't just change it. You the programmer are responsible for drawing abstraction boundaries and choosing the interface.

> It works the exact same way in C++, though.

Only if write C in C++. The issue here are references, of which the compiler figures out whether this should work like a value or like a pointer. This doesn't exist in C, there the programmer needs to make up its mind and choose. The whole type conversion by making a copy issue also doesn't exist there, because either the type matches or the compiler throws an error.

spacechild1•1mo ago
Maybe I misunderstood, but I thought that you were arguing that with link-time optimization the compiler could see through cases such as the one I have given. As a counterargument, I brought up functions that are implemented in shared libraries, which are essential a blackbox to the compiler.

> The issue here are references, of which the compiler figures out whether this should work like a value or like a pointer.

I'm not sure I understand. A C++ reference always has reference semantics. Can you give an example?

jcelerier•1mo ago
> But if vec contains eg long strings, you've now murdered your perf because you're copying them out of the array instead of grabbing refs.

I've seen much more perf-murdering things being caused by

   std::map<std::string, int> my_map;
   for(const std::pair<std::string, int>& v: my_map) {
       ...
   }
than with auto though
dubi_steinkek•1mo ago
Why is this a perf footgun? As someone who doesn't write a lot of c++, I don't see anything intuitively wrong.

Is it that iterating over map yields something other than `std::pair`, but which can be converted to `std::pair` (with nontrivial cost) and that result is bound by reference?

nemetroid•1mo ago
Close, it is a std::pair, but it differs in constness. Iterating a std::map<K, V> yields std::pair<const K, V>, so you have:

  std::pair<const std::string, int>
vs

  std::pair<std::string, int>
1718627440•1mo ago
And what does casting const change, that would involve runtime inefficiencies?
gpderetta•1mo ago
It is not a cast. std::pair<const std::string, ...> and std::pair<std::string,...> are different types, although there is an implicit conversion. So a temporary is implicitly created and bound to the const reference. So not only there is a copy, you have a reference to an object that is destroyed at end of scope when you might expect it to live further.
1718627440•1mo ago
I guess this is one of the reasons, why I don't use C++. Temporaries is a topic, where C++ on one side and me and C on the other side has had disagreements in the past. Why does changing the type even create another object at all? Why does it allocate? Why doesn't the optimizer use the effective type to optimize that away?
jcelerier•1mo ago
> Why does changing the type even create another object at all?

There's no such thing as "changing the type" in c++. Function returns an object type A, your variable is of type B, compiler tries to see if there is a conversion of the value of type A to a new value of type B

nemetroid•1mo ago
Each entry in the map will be copied. In C++, const T& is allowed to bind to a temporary object (whose lifetime will be extended). So a new pair is implicitly constructed, and the reference binds to this object.
verall•1mo ago
Wow I really thought this would be a compile error. The implicit cast here really is a footgun. Looks like '-Wrange-loop-construct' (included in -Wall) does catch it:

> warning: loop variable 'v' of type 'const std::pair<std::__cxx11::basic_string<char>, int>&' binds to a temporary constructed from type 'std::pair<const std::__cxx11::basic_string<char>, int>' [-Wrange-loop-construct] 11 | for (const std::pair<std::string, int>& v: m) {

As they say, the power of names...

whimsicalism•1mo ago
maybe i just do too much c++, but it does seem obvious that auto v : a pattern could lead to a copy
gpderetta•1mo ago
One of the craziest bugs I have had in C++ was due to auto, and it would only trigger when Trump would announce tariffs. It would have been completely preventable if I had paid full attention to my IDE feedback or the correct compiler flags were set.
am17an•1mo ago
This has got to be a hell of a story if it's true.
ajoseps•1mo ago
this sounds hilarious, please do tell. Does it relate to volatility spikes when tariffs are announced and some unexpected overflow?
gpderetta•1mo ago
yes, increased message count because of volatility went over 2*31. The message counter was 64 bit, but a local temporary variable used to read the counter was defined as auto counter = 0;
tigranbs•1mo ago
The last time I worked meaningfully with C++ was back in 2013. Now that I write mostly Rust and TypeScript, I'm amazed by how C++ has changed over the years!

Regarding the "auto" in C++, and technically in any language, it seems conceptually wrong. The ONLY use-case I can imagine is when the type name is long, and you don't want to type it manually, or the abstractions went beyond your control, which again I don't think is a scalable approach.

tialaramex•1mo ago
Type inference is actually very useful you just need to have the right amount, too little and most of your time is spent on bureaucracy, too much and the software is incomprehensible.

In both Rust and C++ we need this because we have unnameable types, so if their type can't be inferred (in C++ deduced) we can't use these types at all.

In both languages all the lambdas are unnameable and in Rust all the functions are too (C++ doesn't have a type for functions themselves only for function pointers and we can name a function pointer type in either language)

1718627440•1mo ago
> C++ doesn't have a type for functions themselves only for function pointers

C has this, so I think C++ has as well. You can use a typedef'ed function to declare a function, not just for the function pointer.

gpderetta•1mo ago
Same in C++. You can't do much with the function type itself as there are no objects with that type, but you can create references and pointers to it.
1718627440•1mo ago
But

    typedef void * (type) (void * args);

    type foo;

    a = foo (b);
works?
meindnoch•1mo ago
Those are function pointers. Your parent was referring to the function type. Per ISO/IEC 9899:TC3:

A function type describes a function with specified return type. A function type is characterized by its return type and the number and types of its parameters. A function type is said to be derived from its return type, and if its return type is T , the function type is sometimes called ‘‘function returning T’’. The construction of a function type from a return type is called ‘‘function type derivation’’.

0xcafecafe•1mo ago
Another place where auto can be useful is to handle cases where the function signature changes without making changes at the calling site. An explicitly typed var would need changing or worse, can work with some potential hidden bugs due to implicit type conversion.
1718627440•1mo ago
This is one of the things static typing is supposed to prevent in the first place. It seems like a lot of people actually want a dynamically typed language, but try to change a static language instead.
andrepd•1mo ago
Things like this are why I don't get when anyone calls Rust "more difficult than C++". I don't think I've ever encountered a more complex and cumbersome language than C++.
nurettin•1mo ago
Rust types can be very verbose, RefCell<Optional<Rc<Vec<Node>>>>

And lifetime specifiers can be jarring. You have to think about how the function will be used at the declaration site. For example usually a function which takes two string views require different lifetimes, but maybe at call site you would only need one. It is just more verbose.

C++ has a host of complexities that come with header/source splits, janky stdlib improvements like lock_guard vs scoped_lock, quirky old syntax like virtual = 0, a lack of build systems and package managers.

andrepd•1mo ago
> Rust types can be very verbose, RefCell<Optional<Rc<Vec<Node>>>>

Anything in any language can be very verbose and confusing if you one-line it or obfuscate it or otherwise write it in a deliberately confusing manner. That's not a meaningful point imo. What you have to do is compare what idiomatic code looks like between the two languages.

C++ has dozens of pages of dense standardese to specify how to initialise an object, full with such text as

> Only (possibly cv-qualified) non-POD class types (or arrays thereof) with automatic storage duration were considered to be default-initialized when no initializer is used. Each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible, if T is a union with at least one non-static data member, exactly one variant member has a default member initializer, if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and each potentially constructed base class of T is const-default-constructible.

For me, it's all about inherent complexity vs incidental complexity. The having to pay attention to lifetimes is just Rust making explicit the inherent complexity of managing values and pointers thereof while making sure there isn't concurrent mutation, values moving while pointers to them exist, and no data races. This is just tough in itself. The aforementioned C++ example is just the language being byzantine and giving you 10,000 footguns when you just want to initialise a class.

1718627440•1mo ago
> > Only (possibly cv-qualified) non-POD class types (or arrays thereof) with automatic storage duration were considered to be default-initialized when no initializer is used. Each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible, if T is a union with at least one non-static data member, exactly one variant member has a default member initializer, if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and each potentially constructed base class of T is const-default-constructible.

That's just a list of very simple rules for each kind of type. As a C++-phob person, C++ has a lot of footguns, but this isn't one of them.

andrepd•1mo ago
This was a random snippet of complicated rules to illustrate what I mean. C++ has significant footguns and complexity when it comes to initialising an object. Even sticking by "Effective Modern C++" rules is a significant cognitive burden on something that should be simple and straightforward. Rust has (mostly) no such footguns; its complexity follows from the essential complexity of the problems at hand.
1718627440•1mo ago
I see. But including a snippet that actually supports your claim would have been more useful.
jpc0•1mo ago
Rust prevents the footgun, but also prevents shooting in the direction where your foot would be even if it isn't there.

There are absolutely places where that is required and in Rust those situations become voodoo to write.

C++ be default has more complexity but has the same complexity regardless of domain.

Rust by default has much less complexity, but in obscure situations outside of the beaten path the complexity dramatically ramps up far above C++.

This is not an argument for or against either language, it's a compromise on language design, you can choose to dislike the compromise but that doesn't mean it was the wrong one, it just means you don't like it.

A relatively simple but complex example, I want variable X to be loaded into a registerer in thos function and only written to memory at the end of the function.

That is complex in C/C++ but you can look at decompilation and attempt to coerce the compiler into that.

In rust everything is so abstracted I wouldn't know where to begin looking to coerce the compiler into generating that machine code and might just decide to implement it in ASM, which defeats the point of using a high level language.

Granted you might go the FFMPEG route ans just choose to do that regardless but rust makes it much harder.

You don't always need that level of control but when you do it seems absurdly complex.

andrepd•1mo ago
> I want variable X to be loaded into a registerer in thos function and only written to memory at the end of the function.

> That is complex in C/C++ but you can look at decompilation and attempt to coerce the compiler into that.

> In rust everything is so abstracted I wouldn't know where to begin looking

I don't know if I fully understand what you want to do, but (1) controlling register allocation is the realm of inline asm, be it in C, C++, or Rust. And (2) if "nudging" the compiler is what you want, then it's literally the same thing in Rust as in C++, it's a matter of inspecting the asm yourself or plonking your function onto godbolt.

1718627440•1mo ago
I think the issue is that naive translation of C into ASM, which is somewhat simulated by -O0, is usable in C, while it isn't in Rust.
jpc0•1mo ago
This.

I agree that you will probably just end up writing ASM but it was a trivial example, there are non-trivial examples involving jump tables and unrolling loops etc.

Effectively weird optimisations that rely on the virtual machine the compiler is building for vs reality, there's just more abstractions with rust than with C++ by the virtue of the safety mechanism, it's just plain not possible to have the one without the other.

The hardware can do legal things that rust cannot allow or can allow but you need to write extremely convoluted code, C/C++ is closer to the metal in that regard.

Don't get me wrong I am all for the right abstractions, it allows insane optimisations that humans couldn't dream of, but there is a flip side.

1718627440•1mo ago
My high level understanding of the UB concept is, that it means false positives to the question "Is that a valid program?". Given that the philosophy of C is mostly "Do what the programmer wrote, no questions asked.", it leads to designing the language so, that the probability of false negatives goes to zero. This obviously means, that the number of false positives goes up.

Rust basically takes the opposite approach of making false positives go to zero, which makes the false negatives go up, which you need to work around with unsafe or type gymnastics.

The third approach is to make both false positives and negatives be zero, by restricting the set of programs, which is what non systems languages do.

nurettin•1mo ago
> Anything in any language can be very verbose and confusing if you one-line it or obfuscate it or otherwise write it in a deliberately confusing manner.

That type was not intentionally obfuscated or complex, it is actually pretty common to see such things. YMMV.

am17an•1mo ago
Usually codebases disallow auto because without an IDE it's difficult to see the type. I think this reduces the cognitive load of C++ a bit. The only time it is allowed is getting iterators types from STL containers.

I remember fretting about these rules when reading Scott Meyer's Effective C++11, and then later to realize it's better not to use auto at all. Explicit types are good types

guenthert•1mo ago
Hard disagree. There are times when nobody, really nobody, cares about a given type. See the example of std::chrono::steady_clock::now over at cppreference.com. There you have

        const auto start = std::chrono::steady_clock::now();
        do_some_work(size);
        const auto end = std::chrono::steady_clock::now();
        const std::chrono::duration<double> diff = end - start;

        std::cout << "diff = " << diff << "; size = " << size << '\n';
Looking up the (current standard's) return type of std::chrono::steady_clock::now() and spelling it out would serve no purpose here.
cjfd•1mo ago
With 'auto' it is so very verbose. It can be shorter. Let us put "using TP = std::chrono::steady_clock::time_point;" in some header file to be used in many places. Now you can write

  TP start = TP::clock::now();
  do_some_work(size);
  TP end = TP::clock::now();
UncleMeat•1mo ago
Some organizations don't like putting using declarations in headers since now you've got a global uniqueness requirement for the name "TP."
dosshell•1mo ago
You put the using as class member (private) or as local in the function.
moregrist•1mo ago
I prefer to put the `using` in the block where you need the std::chrono code, which keeps it local and tidy. Putting it in a header is declaring a global type and asking for trouble; at least bound it in a namespace or a class.
gpderetta•1mo ago
how is TP more descriptive than auto here?
cjfd•1mo ago
I agree that auto should be used as little as possible. There are good uses, though. It is okay to use when the type is trivially inferred from the code. What is auto in "auto ptr = std::make_shared<MyNiceType>();". Everybody who knows any C++ knows. Also, lambdas do not have a type that can be written down, so it is okay to use auto for them.

I also prefer not to use auto when getting iterators from STL containers. Often I use a typedef for most STL containers that I use. The one can write MyNiceContainerType::iterator.

spot5010•1mo ago
Pre LLM agents, a trick that I used was to type in

auto var = FunctionCall(...);

Then, in the IDE, hover over auto to show what the actual type is, and then replace auto with that type. Useful when the type is complicated, or is in some nested namespace.

connicpu•1mo ago
That's what I still do. Replacing auto with deduced type is one of my favorite clangd code actions.
maxlybbert•1mo ago
I know Google’s styleguide discourages auto, but other C++ places I’ve worked weren’t scared of it. The type deduction rules usually do what I expect, unless I have a weird pre-C++11 proxy type that somehow hasn’t been updated in the last 14 years.
moregrist•1mo ago
> Usually codebases disallow auto because without an IDE it's difficult to see the type. I think this reduces the cognitive load of C++ a bit. The only time it is allowed is getting iterators types from STL containers.

Strong agree here. It's not just because it reduces cognitive load, it's because explicit types allows and requires the compiler to check your work.

Even if this isn't a problem when the code is first written, it's a nice safety belt for when someone does a refactor 6-12 months (or even 5+ years) down the road that changes a type. With auto, in the best case you might end up with 100+ lines of unintelligible error messages. In the worst case the compiler just trudges on and you have some subtle semantic breakage that takes weeks or months to chase down.

The only exceptions I like are iterators (whose types are a pita in C++), and lambda types, where you sometimes don't have any other good options because you can't afford the dynamic dispatch of std::function.

nly•1mo ago
Implicit type conversions blow your reasoning out of the water imho

The number of times someone has assigned a return type to int, triggering an implicit conversion.

I'll take "unintelligible compile errors" any day over subtle runtime bugs.

moregrist•1mo ago
I guess it depends on your code base and whether you find more bugs from return values implicitly changed with the usual arithmetic conversions or from other aspects of C++.

I have not encountered that many issues with the usual arithmetic conversions on return types, at least not in a way that auto would prevent. Clearly your experience is different.

Perhaps we can both agree that it would be nice to force explicit numerical conversions?

You can _almost_ get this by wrapping the arithmetic types in a union with only one member, but that may incur a performance hit, which is often not a viable trade off.

> I'll take "unintelligible compile errors" any day over subtle runtime bugs.

As would the rest of us, but that’s not the choice that auto gives you. auto can cause subtle bugs with class types. It doesn’t necessarily protect you from integer narrowing, either, as you eventually have to give the compiler a concrete non-auto type.

112233•1mo ago
There are unspeakble types, such as lambdas, that are not exactly easy to handle without "auto". How a variable containing local lambda with captures will look without "auto"?
dosshell•1mo ago
If it captures variables, it is not possible to manually declare the type. You can however hide it in an std::function. But then you probably get some overhead and some heap allocations in real life.
nly•1mo ago
I use auto everywhere. It makes code a lot more maintainable and easy to reason about in my view.
spacechild1•1mo ago
> Usually codebases disallow auto because without an IDE it's difficult to see the type.

Really? I've never experienced this myself.

Moldoteck•1mo ago
It depends. If you write your code based on abstractions/class features, does it matter ehat type it is? If I call calculation->execute() I don't care what type of object calculation is as long as it can execute and returns something that'll I'll use later for other purpose. To me auto in this case is something similar to using pointers to a base class, but even more abstract
delduca•1mo ago
I use auto everywhere, no regrets.

My LS can infer it anytime.

yearolinuxdsktp•1mo ago
+1 I agree 100% use it everywhere and let LS/IDE infer it.

On top of that:

* Reduce refactoring overhead (a type can be evolved or substituted, if it duck types the same, the autos don't change)

* If using auto instead of explicit types makes your code unclear, it's not clear enough code to begin with. Improve the names of methods being called or variable names being assigned to.

I can see explicit types when you are shipping a library, as part of the API your library exposes. Then you want types to be explicit and changes to be explicit.

rrhjm53270•1mo ago
A trick that I used was

``` struct dummy{}; dummy d = ANYTHING_YOU_WANT_GO_GET_THE_TYPE; ```

Compile it with g++, and get the type info from compilation error -:)

maartenscholl•1mo ago
What is going on with the second element in the final example?

    std::pair x {1, 2.0};
    auto [v, w] = x;
Why is the second element a float according to the blog post?

    std::tuple_element<0, std::pair<int, float> >::type&