Skip to content

Commit

Permalink
Don't Require Floating Point from_chars() Function
Browse files Browse the repository at this point in the history
This commit broadens the scope of commit 2ad332e (PR OPM#922) to
apply to all compilers/libraries, not just Clang/libc++, which do
not have support for floating-point types in std::from_chars().
While hopefully a transient situation, this enables building the
parameter system with GCC versions prior to GCC 11.  We expect to
require version 11 in the not too distant future, though.  At that
point we should revert this commit.

We use a configure-time feature test of the compiler (CMake command
'try_compile') to detect whether or not the compiler supports
floating-point overloads of std::from_chars() and emit the result to
config.h as the new preprocessor symbol

    HAVE_FLOATING_POINT_FROM_CHARS

We use std::strtod() as the fall-back alternative for floating point
conversion if this symbol is defined to false (zero).
  • Loading branch information
bska committed Aug 15, 2024
1 parent 7603f85 commit 3e0aa9f
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 12 deletions.
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ macro (config_hook)
opm_need_version_of("dune-alugrid")
opm_need_version_of("dune-istl")
opm_need_version_of("dune-fem")

# The parameter system can leverage std::from_chars() for
# floating-point types if available. Detect support for this
# feature.
try_compile(
have_float_from_chars
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/cmake/test/testFloatFromChars.cpp
CXX_STANDARD 17
)

set(HAVE_FLOATING_POINT_FROM_CHARS 0)
if(have_float_from_chars)
set(HAVE_FLOATING_POINT_FROM_CHARS 1)
endif()
endmacro (config_hook)

macro (files_hook)
Expand Down
11 changes: 11 additions & 0 deletions cmake/test/testFloatFromChars.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// CMake feature test for floating-point std::from_chars() support

#include <charconv>
#include <string_view>

int main()
{
const auto s = std::string_view { "2.71828" };
auto e = 0.0;
std::from_chars(s.data(), s.data() + s.size(), e);
}
1 change: 1 addition & 0 deletions opm-models-prereqs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set (opm-models_CONFIG_VAR
HAVE_ECL_OUTPUT
HAVE_OPM_GRID
DUNE_AVOID_CAPABILITIES_IS_PARALLEL_DEPRECATION_WARNING
HAVE_FLOATING_POINT_FROM_CHARS
)

# dependencies
Expand Down
19 changes: 7 additions & 12 deletions opm/models/utils/parametersystem.hh
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
#include <dune/common/classname.hh>
#include <dune/common/parametertree.hh>

#include <cstdlib>
#include <charconv>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <list>
Expand Down Expand Up @@ -916,6 +916,7 @@ auto Get(bool errorIfNotRegistered)
const char* const>, std::string,
std::remove_const_t<decltype(Param::value)>>;
ParamType defaultValue = Param::value;

const std::string& defVal = MetaData::mutableRegistry()[paramName].compileTimeValue;
if constexpr (std::is_same_v<ParamType, std::string>) {
defaultValue = defVal;
Expand All @@ -928,19 +929,13 @@ auto Get(bool errorIfNotRegistered)
defaultValue = std::strtold(defVal.data(), nullptr);
}
#endif
#if !HAVE_FLOATING_POINT_FROM_CHARS
else if constexpr (std::is_floating_point_v<ParamType>) {
defaultValue = std::strtod(defVal.c_str(), nullptr);
}
#endif // !HAVE_FLOATING_POINT_FROM_CHARS
else {
#ifdef _LIBCPP_VERSION // If this macro is defined, clang's libc++ is used
// For floating point types, libc++ (the llvm/clang library implementation)
// does not yet (as of clang 15) offer an implementation of std::from_chars().
if constexpr (std::is_integral_v<ParamType>) {
std::from_chars(defVal.data(), defVal.data() + defVal.size(), defaultValue);
} else {
// Floating point workaround.
defaultValue = std::strtod(defVal.c_str(), nullptr);
}
#else
std::from_chars(defVal.data(), defVal.data() + defVal.size(), defaultValue);
#endif
}

// prefix the parameter name by the model's GroupName. E.g. If
Expand Down

0 comments on commit 3e0aa9f

Please sign in to comment.