Cantera / cantera

Chemical kinetics, thermodynamics, and transport tool suite
https://cantera.org
Other
580 stars 341 forks source link

C++ API: compilation error with C++20 or newer #1711

Open tobias-loew opened 2 weeks ago

tobias-loew commented 2 weeks ago

Compiling the C++ API with C++20 or newer results in errors with calls to the fmt library. E.g. with msvc 143, c++latest:

1>D:\loew\proj\cantera\include\cantera\base\ctexceptions.h(89,32): error C7595: 'fmt::v9::basic_format_string::basic_format_string': call to immediate function is not a constant expression 1>D:\loew\proj\cantera\include\cantera\base\AnyMap.h(749,64): error C7595: 'fmt::v9::basic_format_string<char,const std::string &,const std::string &>::basic_format_string': call to immediate function is not a constant expression 1>D:\loew\proj\cantera\include\cantera\base\ctexceptions.h(89,32): error C7595: 'fmt::v9::basic_format_string<char,const double &>::basic_format_string': call to immediate function is not a constant expression 1>D:\loew\proj\cantera\include\cantera\base\ctexceptions.h(89,32): error C7595: 'fmt::v9::basic_format_string<char,const std::string &,const std::string &,const std::string &>::basic_format_string': call to immediate function is not a constant expression 1>D:\loew\proj\cantera\include\cantera\base\global.h(231,46): error C7595: 'fmt::v9::basic_format_string::basic_format_string': call to immediate function is not a constant expression

The version of the fmt submodule is outdated and should be updated to a recent version.

Try to compile the simple-demo with C++20 or newer on msvc

#include "cantera/core.h"
#include <iostream>

using namespace Cantera;

// The actual code is put into a function that can be called from the main program.
void simple_demo()
{
    // Create a new Solution object
    auto sol = newSolution("h2o2.yaml");
    auto gas = sol->thermo();

    // Set the thermodynamic state by specifying T (500 K) P (2 atm) and the mole
    // fractions. Note that the mole fractions do not need to sum to 1.0 - they will
    // be normalized internally. Also, the values for any unspecified species will be
    // set to zero.
    gas->setState_TPX(300.0, 2.0 * OneAtm, "O2:1.0, H2:2.0, AR:1.0");
    gas->equilibrate("TP");

    // Print a summary report of the state of the gas.
    std::cout << gas->report() << std::endl;
}

// The main program just calls function simple_demo within a 'try' block, and catches
// CanteraError exceptions that might be thrown.
int main()
{
    try {
        simple_demo();
    }
    catch (CanteraError& err) {
        std::cout << err.what() << std::endl;
        return 1;
    }
    return 0;
}

Behavior

compilation errors

System information

Attachments

Additional context

speth commented 2 weeks ago

You aren't obligated to use the submodule version of fmt. You can install whatever version you like and use it as a system dependency. That said, I don't think we've ever tested compiling Cantera with the compiler set to use the C++20 standard, so there may be other issues there.

speth commented 1 week ago

After further investigation, the issue is not with fmt version 9.1.0. Rather, the issue is with some compile-time checks that are enabled by fmt when compiling in C++20 mode that require changes to the Cantera source. The fmt documentation provides a bit of info. The gist of it is that in cases where the format string isn't a compile-time constant, it needs to be wrapped in fmt::runtime.

I've started a branch with these changes here. It needs some work to ensure that we're actually backwards compatible as far we want to be, and to test this as part of the CI.

One somewhat odd behavior I found was that I didn't get any errors compiling with C++20 mode using Apple Clang on macOS, even without these changes.

tobias-loew commented 1 week ago

just as a note: this problem occurs when trying to compile one of the examples. so C++ Cantera users are currently forced to use C++17 or earlier.