diff --git a/src/libraries/JANA/Services/JParameterManager.h b/src/libraries/JANA/Services/JParameterManager.h index 8cede5a2b..70255898d 100644 --- a/src/libraries/JANA/Services/JParameterManager.h +++ b/src/libraries/JANA/Services/JParameterManager.h @@ -311,12 +311,25 @@ inline T JParameterManager::RegisterParameter(std::string name, const T default_ } -/// @brief Logic for parsing different types in a generic way +#if __cplusplus >= 201703L +/// @brief Basic implementation of Parse for C++17 and newer. Provides a helpful error message when attempting to parse a type that doesn't come with a stream operator. template -void JParameterManager::Parse(const std::string& value, T& val) { - std::stringstream ss(value); - ss >> val; +void JParameterManager::Parse(const std::string& s, T& out) { + constexpr bool parseable = JTypeInfo::is_parseable::value; + static_assert(parseable, "Type is not automatically parseable by JParameterManager. To use, provide a template specialization for JParameterManager::Parse(std::string in, T& out)."); + if constexpr (parseable) { + std::stringstream ss(s); + ss >> out; + } } +#else +/// @brief Basic implementation of Parse for C++14 and earlier. +template +void JParameterManager::Parse(const std::string& s, T& out) { + std::stringstream ss(s); + ss >> out; +} +#endif /// @brief Specialization for string. @@ -360,13 +373,28 @@ inline void JParameterManager::Parse(const std::string& value, std::vector &v } } -/// @brief Logic for stringifying different types in a generic way +#if __cplusplus >= 201703L +/// @brief Basic implementation of Stringify for C++17 and newer. Provides a helpful error message when attempting to stringify a type that doesn't come with a stream operator. +template +inline std::string JParameterManager::Stringify(const T& value) { + constexpr bool serializable = JTypeInfo::is_serializable::value; + static_assert(serializable, "Type is not automatically serializable by JParameterManager. To use, provide a template specialization for JParameterManager::Stringify(const T& val) -> std::string."); + if constexpr (serializable) { + std::stringstream ss; + ss << value; + return ss.str(); + } +} +#else +/// @brief Basic implementation of Parse for C++14 and earlier. template inline std::string JParameterManager::Stringify(const T& value) { std::stringstream ss; ss << value; return ss.str(); } +#endif + template <> inline std::string JParameterManager::Stringify(const float& value) { diff --git a/src/programs/tests/JParameterManagerTests.cc b/src/programs/tests/JParameterManagerTests.cc index 19209af77..b509d6eda 100644 --- a/src/programs/tests/JParameterManagerTests.cc +++ b/src/programs/tests/JParameterManagerTests.cc @@ -402,32 +402,16 @@ TEST_CASE("JParameterManager_Issue217StringsWithWhitespace") { } } -#if __cplusplus >= 201703L -template -void fakeParse(std::string s, T& out) { - constexpr bool parseable = JTypeInfo::is_parseable::value; - static_assert(parseable, "Type is not automatically supported by the ParameterManager. To use, implement a template specialization for Parse(std::string in, T& out)."); - if constexpr (parseable) { - std::stringstream ss; - ss >> out; - } -} -#else -template -void fakeParse(std::string s, T& out) { - std::stringstream ss; - ss >> out; -} -#endif -} - enum class Mood {Good, Bad, Mediocre}; -TEST_CASE("Error message on bad parse") { +TEST_CASE("JParameterManager_CompileTimeErrorForParseAndStringify") { + int x; - fakeParse("22", x); + JParameterManager::Parse("22", x); Mood m; - fakeParse("Mediocre", m); + // Uncomment these to test compile-time error message + //JParameterManager::Parse("Mediocre", m); + //JParameterManager::Stringify(m); }