Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++11? #8

Open
vinniefalco opened this issue Oct 5, 2020 · 38 comments
Open

C++11? #8

vinniefalco opened this issue Oct 5, 2020 · 38 comments

Comments

@vinniefalco
Copy link

I need a port of this to C++11

@jk-jeon
Copy link
Owner

jk-jeon commented Oct 6, 2020

It'll be a lot of work. Since the new quarter has begun, I can't afford much time to it, but I'll try.

@stainleebakhla
Copy link

Would love it if C++11 version of this is made available. Great work guys!

@ecorm
Copy link

ecorm commented Mar 27, 2021

I'm sure everyone here already knows this, but I'll mention it for those who don't: constexpr if can be emulated in C++11 by tagged dispatching using std::true_type and std::false_type:

Instead of

if constexpr(condition)
{
    do_this(arg1);
}
else
{
    do_that(arg2);
}

one can do:

do_this_or_that(std::integral_constant<bool, condition>{}, arg1, arg2);

inline void do_this_or_that(std::true_type, int arg1, int arg2)
{
    do_this(arg1);
}

inline void do_this_or_that(std::false_type, int arg1, int arg2)
{
    do_that(arg2);
}

Any decent compiler will optimize this into the equivalent if constexpr code.

The downside of course is more code, and the need to pass variables as arguments. The upside is compatibility with C++11 and (presumably) wider adoption.

std::bool_constant doesn't exist prior to C++17, but one can easily define their own template alias that does the same thing:

template <bool condition>
using meta_bool = std::integral_constant<bool, condition>;

then

do_this_or_that(meta_bool<condition>{}, arg1, arg2);

EDIT: Added the missing inline that I forgot.

@ecorm
Copy link

ecorm commented Mar 27, 2021

According to this 2020 survey, 46% responded that they regularly use C++11, so it's far from being dead.

I can understand wanting to use the latest C++ features for writing an in-house application, but for open-source libraries, IMHO, it's better to be conservative in the minimum C++ version required if you want the widest possible adoption.

@vinniefalco
Copy link
Author

if you want the widest possible adoption.

GitHub stars and forks are what give my life meaning and value

@ecorm
Copy link

ecorm commented Mar 28, 2021

GitHub stars and forks are what give my life meaning and value

@vinniefalco, I'm working on a serialization library intended to be used in conjunction with Asio and your Beast library. It's currently closed source, but I may be able to convince my employer to make it open source in the future. I'm deliberately constraining my serialization library to C++11 so that its language requirements matches that of yours. I would love to make use of Dragonbox for fast float-to-string conversions, but it would then artificially bump the requirements of my library up to C++17.

@vinniefalco
Copy link
Author

vinniefalco commented Mar 28, 2021

I would love to make use of Dragonbox for fast float-to-string conversions

I agree that requiring C++17 will definitely reduce the size of the potential audience. If you want, you could just crib the RYU algorithm from Boost.JSON which perform float-to-string conversions. It is comparable in terms of performance and requires only C++11:
https://github.com/boostorg/json/tree/develop/include/boost/json/detail/ryu

Or you can use the original Ryu which I think is in C? https://github.com/ulfjack/ryu

@vinniefalco
Copy link
Author

I failed to understand why you cannot build the latest toolchain/cross-toolchain. It is extremely simple okay?

If this was universally true, you wouldn't see so many projects which still use C++11.

@vinniefalco
Copy link
Author

That is universally true.

Then why are there so many projects which use C++11? From https://www.jetbrains.com/lp/devecosystem-2020/cpp/

image

Why are 46% of projects using only C++11? If it is "extremely simple?"

@ecorm
Copy link

ecorm commented Mar 28, 2021

Let's keep the discussion civil.

that is not zero-overhead tbh. On Microsoft ABI, even empty objects would waste registers

If the code is all inline, wouldn't the compiler optimize the function call away, regardless of ABI?

I failed to understand why you cannot build the latest toolchain/cross-toolchain. It is extremely simple okay? Even on windows.

It's not me you need to convince, but the 46% of my library's potential audience who still use C++11 (see survey link in my above post). If it were a in-house project, then I could of course use the latest toolchains if I so choose.

Another thing to keep in mind is that many open source projects are included in Linux distros, so they are constrained to the "standard" compiler versions used in those distros.

To be fair, I can understand the point of view that new libraries adopting C++17 helps to the encourage the industry in moving on past C++11. I guess it's up to the author to decide what's important for them: wider adoption or the joy/convenience of using the latest C++ language features.

@vinniefalco
Copy link
Author

If the code is all inline, wouldn't the compiler optimize the function call away, regardless of ABI?

Yes, the compiler sees right through it with full optimizations turned on. And if it doesn't, that's a problem with the compiler which should be fixed there as well.

@vinniefalco
Copy link
Author

It seems there are diminishing returns (really, no returns) on additional dialogue with this individual.

@ecorm
Copy link

ecorm commented Mar 28, 2021

@vinniefalco He got kicked out of the Reddit C++ subforum, as well as the Ryu Github repo. Not hard to imagine why.

@ecorm
Copy link

ecorm commented Mar 28, 2021

You don't pay the author either. We're simply making a feature request and presented some evidence on the number of C++11 users. I'm trying to stay civil here, but you turned this into a angry rant. Even if you're technically correct, people won't take you seriously if you don't remain calm and respectful.

If you admire Linus Torvalds so much, perhaps you should do like him and try to learn some empathy: https://arstechnica.com/gadgets/2018/09/linus-torvalds-apologizes-for-years-of-being-a-jerk-takes-time-off-to-learn-empathy/

Of course if the author declines this C++11 feature request, I'll respect that decision and will use another alternative, such as Ryu, or forking this project.

I have said all I have to say about this subject. Good day to you.

@ecorm
Copy link

ecorm commented Mar 28, 2021

I know people are hating me because I am speaking the sad truth.

There are ways of arguing what you believe is the truth without coming off as a jerk. It's not what you say that people dislike, it's how you say it that comes off as insulting. I'm not telling you this to belittle you, but to help you become a better person.

If you call other people's work "trash", then it's the same as insulting those people directly. One can critique another person's work without being insulting.

If you can have people respect you for both your knowledge and your good manners, then you will truly become an individual with "power".

@jk-jeon
Copy link
Owner

jk-jeon commented Mar 28, 2021

Oh god. What's happening here 😅

@ecorm Thanks for the statistics, the percentage of C++11 looks greater than I expected. It sounds worth to give a try. Right now I do not have time, probably until the beginning of the summer break. Probably I'll work on it after dealing with the items in my personal to-do queue, like coming up with a solution for the issue #11, updating the benchmark, etc..

FYI, @abolz has reimplemented Dragonbox, and AFAIK this implementation does not have lots of compiler-torturing nonsenses mine has, so it is probably C++11 or C++03. He also has an arguably better decimal-to-string conversion routine, which requires a little bit more preconditions but has greater performance. You might be interested to check out the repository.

(It was my goal to provide as many customization options as possible because I aimed to provide a library that serves as a building block for float-to-string conversion library, not such a library itself. That's one reason for those compiler-torturing nonsenses. Another (possibly-related) reason is that I hate magic numbers and tried to minimize their occurrences. Probably these are just overengineering, common to amateurs😕)

Or, fmt should be a viable option as well, which uses Dragonbox internally. Since the version 7.1.0, it has far better performance compared to the version I tested against in the benchmark. And I believe fmt is compatible with C++11. Could be C++14, but I think fmt is targeting C++11 and any presence of non-C++11 features should be bugs that you can report.

@ecorm
Copy link

ecorm commented Mar 28, 2021

@jk-jeon Thanks for the information. I was unaware of abolz' implementation. It looks like it's just what I need with Javascript-like behavior for use with JSON.

@vinniefalco
Copy link
Author

I aimed to provide a library that serves as a building block for float-to-string conversion library

I discovered on my own that converting a number between base 2 and base 10 is in fact quite difficult :) Thank you for this library.

@jk-jeon
Copy link
Owner

jk-jeon commented May 14, 2021

Given that the implementation embedded in fmt is already C++11-compatible, re-extracting that into a separate repo should not be a big effort. The ported version will have a much smaller set of configurable policies, but it should not be a big issue to most of the potential users.

But before doing that, I'd like to change some interfaces (and finally release the version1 tag). I'll get back to this after that.

@robhz786
Copy link

robhz786 commented May 23, 2021

Hi,
I know this conversation is about C++11, but anyway, in case anyone is interested, I have just adapted the code to C++14, in the branch cxx14, in my fork.

It might be not that difficult to convert it from there to C++11.

Btw, thanks for this amazing algorithm.

@jk-jeon
Copy link
Owner

jk-jeon commented May 24, 2021

@robhz786 Oh thank you so much! I'll refer to it when I work on the C++11 port!

@ecorm
Copy link

ecorm commented May 26, 2021

Going back to the use of if constexpr statements... If the condition is a known constant at compile-time, all decent compilers will optimize-out the branch never taken. Instead of if constexpr, you could do something like:

#if __cplusplus >= 201703L
#define JKJ_CONSTEXPR_IF if constexpr
#else
#define JKJ_CONSTEXPR_IF if
#endif

This of course assumes that the leftover unused branch does not result in compile errors in the case of a simple if statement. I didn't bother to check in the code where if constexpr could be safely substituted with JKJ_CONSTEXPR_IF, but I just wanted to pass along the general idea.

@ecorm
Copy link

ecorm commented May 15, 2022

C++ language standards adoption from the jetbrains report done in 2021:

C++ language standards adoption

@jk-jeon
Copy link
Owner

jk-jeon commented May 17, 2022

@ecorm Thanks for sharing this!

I'm planning C++11 support (along with constexpr support for C++20) for the next release!

@ecorm
Copy link

ecorm commented Jan 16, 2023

Jetbrains have not published any infographics of their 2022 survey.

There is, however, page 19 of the 2022 Annual C++ Developer Survey "Lite", presumably run by the ISO committee.

Snapshot of relevant chart, which I share here under the Fair Use Doctrine for the purpose of discussion:

Screenshot from 2023-01-16 17-43-06

For C++17, 20% have responded "Partial: Lim...", and around 12% have responded "No: Not allo...". Compare that to ~8% and ~2% respectively for C++11.

Please note that this is not a "nag" to support C++11 for this library. It's just that this issue has become a convenient place for me to keep track of C++11/C++17 usage throughout the years. 😁

@alugowski
Copy link

alugowski commented Jan 20, 2023

Great chart, @ecorm . It does show that a C++11 version would gain a potential user base of 1/5 of respondents. The previous plots have to be taken with a pinch of salt. Just because someone is using C++11 does not mean they can't or won't use something newer.

As much as I agree about library compatibility, I think @jk-jeon should feel free to not make it a priority. This is an academic endeavor, after all, and grad school will absolutely not reward the effort (been there). And it must be a lot of effort, as no-one has submitted a PR in 2.5 years. If anything, it would be a net negative because it would make further research harder as the code would be more difficult to work with.

@jk-jeon
Copy link
Owner

jk-jeon commented Jan 21, 2023

@alugowski Thanks so much for your kind words.

This is an academic endeavor, after all, and grad school will absolutely not reward the effort (been there).

Haha. This project indeed has nothing to do with what I'm supposed to do in my grad school life. I'm really not supposed to waste my time on this but I just can't stop it because it's so fun. At this point I am trying to minimize my time working on this, but I'll never entirely give up on this project.

@ecorm
Copy link

ecorm commented Feb 5, 2023

It does show that a C++11 version would gain a potential user base of 1/5 of respondents.

If you look at the "No: Not Allowed" column on page 20, the difference between C++11 and C++17 is only around 10%. I'm starting to question my own self-imposition of C++11 in my open-source libraries. It would be nice to get rid of my string_view and optional polyfills, as well as being able to use if constexpr, generic lambdas, auto return types, etc.

@alugowski
Copy link

It does show that a C++11 version would gain a potential user base of 1/5 of respondents.

If you look at the "No: Not Allowed" column on page 20, the difference between C++11 and C++17 is only around 10%. I'm starting to question my own self-imposition of C++11 in my open-source libraries. It would be nice to get rid of my string_view and optional polyfills, as well as being able to use if constexpr, generic lambdas, auto return types, etc.

You are far more patient than I. One datapoint is what Python extensions can be safely built in. That's been C++17 for quite a while. And most are built in a container with 2014 in its name ;)

@jk-jeon
Copy link
Owner

jk-jeon commented Aug 12, 2023

Features needed to be replaced:

  • Terse static_assert
  • inline constexpr variables
  • Structured bindings
  • constexpr table building
  • Some other instances of generalized constexpr functions (Done except for the policy nonsenses)
  • XXX_v inline variables for <type_traits>
  • XXX_t type aliases
  • if constexpr
  • Deduced return type
  • Digit separators
  • Nested namespace definition

@mborland Dear Matt, if this doesn't take your precious time too much, could you let me know of anything else you recall?

@mborland
Copy link

Those are most of the big ones. Lesser issues:

  • Lambdas with auto parameters. I replaced those with template functions
  • You have the inline constexpr variables, but I found to work with old compilers the cache structs needed to be templated. An example is here. Since the static variables are implicitly inlined you'll hit linker issues quickly.
  • For deduced return types coming from the policies I ended up just hard-coding the policy I wanted in C++11 mode. I have already added trailing return types to most things if you save some time
  • I replaced if constexpr with std::enable_if templates in most places. Dispatching on true/false type would work equally well.
  • Most of the constexpr functions were as easy as replacing constexpr with BOOST_CONSTEXPR which just generally just checks the values of the feature test macros.

If you want to reference anything I refactored all of the dragon box and floff code in charconv to be in a folder by itself here. I support back to Clang 3.5 and GCC 5. I ended up dropping the GCC 4.X series because of broken aggregate initialization of u128 in the caches. Let me know if you have any additional question and I'll do my best to answer them.

@jk-jeon
Copy link
Owner

jk-jeon commented Aug 14, 2023

@mborland Thanks a lot, it's really helpful!

@jk-jeon
Copy link
Owner

jk-jeon commented Aug 15, 2023

I mostly finished this but I need some rigorous testing. I'll do it shortly but PR is welcomed!

@jk-jeon
Copy link
Owner

jk-jeon commented Aug 15, 2023

Okay, it now at least compiles successfully with:

C++11:

  • Clang >= 3.7
  • GCC >= 5.1

C++14:

  • Clang >= 3.7
  • GCC >= 5.1
  • MSVC >= 19.14

C++17:

  • Clang >= 5.0
  • GCC >= 5.1
  • MSVC >= 19.14

C++20:

  • Clang >= 10.0
  • GCC >= 10.1
  • MSVC >= 19.30

Still PR's with a decent set of tests is very much welcomed!

@vinniefalco
Copy link
Author

Wow, that's pretty amazing :) Thank you so much. It is true that C++11 is getting pretty old, and my general advice is to target C++ for new libraries. However for something like this, which is such a profound low-level building block that has performance implications, giving people stuck on C++11 access to using the library is a bigger win. Thanks.

@ecorm
Copy link

ecorm commented Apr 18, 2024

ISO's 2024 Annual C++ Developer Survey "Lite" is out: https://isocpp.org/files/papers/CppDevSurvey-2024-summary.pdf

image
image

"Pretty much all" for C+11 is 91% versus 78% for C++17.

@jk-jeon
Copy link
Owner

jk-jeon commented Apr 18, 2024

@ecorm I remember you said you're just using this thread as a convenient place for tracking the language standard adoption, but I will use your posting as an opportunity to write down the remaining stuffs that need to be done😃

  • Provide a CMake option for switching between language standards.
  • Update test codes that remain as C++17+ only. I don't plan to update all test/meta codes to be C++11-compatible, but some needs to be.
  • Update CI to test various standards.

Once these are done I will close this issue. Hopefully in the near future!

@ecorm
Copy link

ecorm commented Apr 18, 2024

@jk-jeon I'm now adopting C++17 as the minimum version for my libraries, but float/string conversion library is far more fundamental than the niche stuff I'm doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants
@vinniefalco @alugowski @mborland @ecorm @robhz786 @jk-jeon @stainleebakhla and others