47 comments

[ 3.0 ms ] story [ 91.0 ms ] thread
I don't get why C++ programmers like to keep the namespace prefixes around. I'd just add lots of "using ..." statements and make my code more readable. What's the chance of conflicts anyway when you are already dealing with a tiny fraction of the code in the current file?
It's a header-only library, it would effectively add "using" statements anything that included the library.
Ouch. Seems like an unsolvable limitation at this point. Nice catch.
C++20 introduces “modules” which are an attempt at alleviating the problem of headers. Support, though, is lacking in major compilers’ master branch. GCC supports it if you build a certain branch from source though.
Some really prompt bugfixing on C++ committee's part. "We have a broken compilation process that leads to humongous build times and namespace pollution! Oh, OK, let's wait another 20 years to fix it".

I guess C++ coders deserve the std::'s their language gives them.

It's actually possible to avoid this!

  namespace foo::_bar {
      using namespace ::acme::widgets;
      /* internal helpers go here */
      inline namespace exports { /* public API goes here */ }
  }

  namespace foo::bar { using namespace _bar::exports; }
Besides the header issue mentioned in the sibling, sometimes the context is important too, for an example from Python, no one would `from os.path import join`— you always use `os.path.join` in its entirety.
(comment deleted)
I agree with your point and I'm just nit picking, but `from os import path` and `path.join` is pretty acceptable too.
I have definitely seen `from os.path import join` in some ugly ML github repos.
:shrug: I've done that quite a bit. This randomly selected popular Python library does it, too[1]. The example for `os.walk` literally has `from os.path import join, getsize`[2]. The docs seem to back this up[3]:

"Remember, there is nothing wrong with using `from package import specific_submodule!` In fact, this is the recommended notation unless the importing module needs to use submodules with the same name from different packages."

I haven't dealt with a lot of C++ code but I feel like I see a lot of `using namespace ...` and haven't seen much `using ...;` (which I think is more readable/acceptable)

[1] https://github.com/psf/requests/blob/df918c066fa275abc2bb0c9...

[2] https://docs.python.org/3/library/os.html#os.walk

[3] https://docs.python.org/3/tutorial/modules.html#importing-fr...

You could do that in .cpp files, but it's objectively bad to do so in the header files due to namespace pollution. And now you have an inconsistency between headers and .cpp files..
Why do header files even exist and why do sane languages work without them? Oh, I forgot, you cannot question The Holy Warts of Stroustrup. It's just C++. Leave all hopes of developer productivity at the door.
> C++17

> Works with or without exceptions

Is anyone using C++17 features with exceptions disabled? I thought the “no exceptions” people were generally only using C++ as C-with-classes?

All of Google's codebase, including Chromium, is OO C++ without exceptions.

https://google.github.io/styleguide/cppguide.html#Exceptions

In other words, that codebase is without exceptions, without exception.
std::bad_alloc would like to have a word with you.
An exception that proves the rule.
Thanks - I’d seen that section before, but hadn’t noticed that elsewhere the document says “code should target C++17“.

Do you know if there are any parts of the C++17 language or standard library that are disallowed in Google’s code because those parts don’t work without exceptions?

No, nothing in C++ has a hard dependency on exceptions. Custom allocators can be used to report allocation failures in some way other than throwing an exception, and other than that the standard library only uses exceptions to report precondition violations; things which are expected to sometimes fail (such as filesystem operations) can report error codes instead.
Let's insist on

> On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. If exceptions can be propagated beyond a new project, it also becomes problematic to integrate the new project into existing exception-free code. Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions.

Also let's note that there are more new C++ projects being created today that at any previous point in time.

Propagating the -fno-exceptions meme is harmful to the whole community.

Yes, plenty, including Google.

If anything exceptions are declining in popularity, due to non-obvious and non-local effects.

Exceptions are an uber-goto, that can jump outside entire functions. Some people still like that, but very disciplined code bases (of which there are a lot in C++) tend to avoid them.

At the very least, utility libraries like this one tend to err on the side of most compatible: header only, no exceptions, user-chosen allocators, etc.

Thanks. Do you know what the knock-on effects are of disabling exceptions in modern C++? Are there parts of the language or standard library that won’t work without exceptions?
The standard library uses exceptions, but in ways that are avoidable.

Not using exceptions does necessitate avoiding the `new` operator, or allowing your program to terminate on OOM.

[1] https://stackoverflow.com/questions/37700365/if-youre-in-the...

[2] https://news.ycombinator.com/item?id=13354027

Many of the large C++ projects I've been on are exceptionless, but do throw an OOM exception which is caught at a very high level. That's usually the point where a crashdump is taken and some other forensics are gathered; a decent strategy is to freeze threads (if you can), release some reserve memory and try to gather evidence. Doesn't always work . . .
Some "exceptionless" projects actually disable exceptions entirely via compiler flag.
> Exceptions are an uber-goto, that can jump outside entire functions. Some people still like that, but very disciplined code bases (of which there are a lot in C++) tend to avoid them.

I've never heard discipline as a reason to be exceptionless, its always been performance related (specifically performance predictability).

Discipline can be mean strong performance too.

In any case, exceptions are really only a performance problem if there are frequent. [1] Modern compilers and machines have near zero overhead for unthrown exceptions and 20x the overhead of an if-else.

Chances are quite good that you have bigger performance problems than exceptions.

[1] https://stackoverflow.com/questions/13835817/are-exceptions-...

Like I said, performance predictability, not raw performance. if/else have predictable performance characteristics, while exceptions are fast usually and then occasionally very slow.

The idea being that in an area where you'd like performance to be predictable, even in cases of unexpected results, Sum types or if/else give the same performance all the time.

> Like I said, performance predictability, not raw performance.

Your argument makes absolutely no sense. Exceptions are used to handle exceptional events, the kind of stuff that would crash and shutdown your program. Exceptions are used to establish sanity checkpoints where any exceptional event can be caught and either recover from it or fail gracefully. Performance is measured on the happy path, and exceptions fall in the exact opposite of the happy path.

There are cases where you want exceptional performance to also have predictable characteristics. I don't know why that doesn't make sense.
> Yes, plenty, including Google.

Your statement is either disingenuous or entirely clueless.

The only rationale that Google presented to not use exceptions is that they use a lot of legacy code that was designed without exception handling, and thus it's problematic for then to integrate modern C++ code with old exception-free code. For Google, the only problem with exceptions is their own personal technical debt. That's it. It's in their FAQ.

Enough with this nonsense.

https://google.github.io/styleguide/cppguide.html#Exceptions

> Exceptions are an uber-goto, that can jump outside entire functions.

That statement is far from being correct or an appropriate description. Exceptions are as much like goto statements as are return statements, and no one in their right mind would describe a return statement as an uber-goto statement.

> Some people still like that, but very disciplined code bases (of which there are a lot in C++) tend to avoid them.

Again, that assertion makes no sense at all.

I'm a "no exceptions, no exceptions" person. I mostly use C++ as C-with-templates, rather than C-with-classes, so C++17 is very useful to me.
In my experience, few people use exceptions in systems-style code like database engines, while still using every feature of the latest versions of C++. You can essentially use all of C++17 without them if you wish, and many people do. Definitely not C-with-classes style code.
According to a recent talk from Herb Stutter (https://www.youtube.com/watch?v=ARYP83yNAWk), as many as 20% of users fully ban exceptions and an additional 30% ban them partially.

Even code doesn't actually reach the throwing paths, exceptions and RTTI induce a huge binary size overhead that is simply not acceptable if you have binary size constraints.

Low level programmers dislike exceptions because cost, high level (and some low level) programmers dislike exceptions because they make any reasoning about behaviour, resource leaking, etc impossible without looking at the full code, and even then the analysis is exponentially more difficult.

This all applies regardless of the C++ standard, of course.

What are the advantages of this library over, say https://github.com/ToruNiina/toml11 ?
I actually tried using toml11 before writing toml++, and my main gripe with it was the complexity. It does a _lot_, and I found it to be pretty unergonomic to actually use.

That, and it's not as configurable (e.g. no support for exception-less).

I'm a bit surprised by this snippet from the "Traversing and manipulating data" example:

  for (auto& elem : *arr) {
      // visitation helps deal with the polymorphic nature of TOML data
      elem.visit([=](auto&& el) noexcept
      {
          if constexpr (toml::is_number<decltype(el)>)
              (*el)++;
          else if constexpr (toml::is_string<decltype(el)>)
              el = "five"sv;
      });
  }
I thought constexpr would work at compile time but how can the compile here inside a loop "know" when this labmda will encounter an int or a string ?
It's tricky but I think visit is being passed a generic (templated) lambda, which is statically instantiated for each type that a node might be. (Once for int, once for string, etc) Since the type is static per template instantiation, constexpr works here.
Thank you for the explanation!
Hm, it looks like it is using things like std::vector and streams, etc.

So it does actually require exceptions and RTTI/still forces linkage against throwing functions, etc.

Sure, if you want to be pedantic: it works without them when paired with standard implementations that can work without them
In no-exception builds, exceptions become crashes. RTTI is barely used anywhere in the STL.

As an example, Firefox uses STL without RTTI or exceptions.