are constexpr functions that load files possible i

2020-07-07 11:36发布

问题:

There was a similar question here but it had no valuable information so I want to ask this again - is it possible to load contents of an arbitrary file using a constexpr function? I know that this seems impossible since all the possible functions that allow file I/O (fopen, open ...) are not constexpr so cannot be called in this scenario. However - since there are many people here who follow the development of c++17 and on - is there any hope that further standards will include some file I/O API that will be constexpr and could be used to load a file at compile time?

Just for a comparison - Haxe allows to do almost anything via the compile time macros, so it would be very cool to have something similar in C++. For example, generating class instances by deserializing files.

回答1:

This is (to me at least) a typical case of over-complication when moving between languages. Yes, you could implement functionality to add compile-time file loading into C++, we could also add runtime-reflection. However in my opinion these aren't necessary, nor wanted features.

If you have the skill to write a program that needs a constexpr, you can comprehend the concept of pre-build events (to use the Microsoft terminology), should you be capable of reading a file, you should be sufficiently capable of writing code to parse files into other formats.

In this situation, the compile-time solution is to write a stand-alone tool that will parse the file in question, and generate a .h (header) file containing the required constants and evaluations of those constants. This tool can then be run before your build-process is run.

Thus your constexpr becomes exactly that, a constant expression

Take the example of a "program version number", the common solution is to have a developers IDE, or stand-alone tool, create a header-file containing the constant values that are the version of the software.

Many FOSS software's contain such functionality in their ./configure scripts - parsing the current revision number from Git or alike - thus meaning that any built-version of the software can output the build-number, allowing issue tracking.

In short - I would be very surprised and disappointed if c++17 or any other future version presented the functionality you are looking for - doing so adds a requirement to understand the file-system of the user, and only succeeds in implementing functionality best left to the end user.

However, we should not fall into the trap of trying to add every possible feature to it in an attempt to please everyone.~ Bjarn Stroustrup

In layman's terms, it would be like selling a push-bike along with a single-size helmet and biking shorts (that the user is legally required to use). It might fit the needs of most users, but attempting to fit into said shorts with my waistline would be... problematic.

Imagine the complexities added for cross compilers between architectures, embedded systems, etc.

[edit/]

This isn't perhaps a perfect answer - and is to some degree opinion based; What I'm attempting to provide is an understanding that while arguably most users are desktop-oriented, adding something like this would immensely complicate compiler development for embedded systems and other applications. And this is what C++ is trying to avoid.

Some light reading

[edit 2/]

It was indicated in the comments "why not just have the compiler just add the file-contents as a char *, and that is a great question! In this regard I have two points to raise.

  1. Are you going to parse that char* in the constantexp? If so, then you are going to need a loop, and variables - things that you can't use reliably.
  2. If you want a string literal of the file contents - it's not pretty but C++'s preprocessor can do this (assuming the file-format doesn't contain invalid characters).

And again - anything more complex than these simple examples becomes complex enough to be hard to define in the standard, should the file be binary? should it be text? What are the line-endings? should it be parsed?

Meanwhile, you could easily Use existing tools, even doing so in combination with other methods. For example, write a tool that will parse your binary file, re-encode it as a series of escape sequences (eg: \0x0, \0x12, \0x22), have it automatically added to a header file defining a pointer to said data. Then #include that header - You have what you want, for the platforms your working on, and haven't possibly created loopholes in the C++ standard that may cause inherent complexity.

Please remember that C++ as a language is finally recovering from a very-long spate of Very Bad Press. And Compilers that to this day Still act totally-differently in some instances.

In my opinion, Every C++ programmer wants a world where I can write my "perfectly object oriented C++ code once" and then it will just work on everything from a 1990's Nokia-phone, through to the latest quantum-optical-univac. And finally we are getting a little bit closer to doing so, to proving the worth of C++ to the wider world. Firing our death-star beam at Java, or somesuch provocative statement.

Thus, I say - The idea is nice, but not-needed. Of course, if you'd like to write a Full Proposal, outlining how you will avoid any issues that could hurt the future C++-Utopia, I would beg you to do so. If a feature like this can be done without hurting the pre-processor, platform independence, creating Impossibly complex errors, or alike. Then you'd be smarter than me - Because I can't see how that would be possible currently.



标签: c++ constexpr