Skip to content

Commit

Permalink
Add constexpr type checks to JParameterManager::Parse,Stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanwbrei committed Oct 9, 2023
1 parent 38f13ef commit 1abda35
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 27 deletions.
38 changes: 33 additions & 5 deletions src/libraries/JANA/Services/JParameterManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T>
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<T>::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 <typename T>
void JParameterManager::Parse(const std::string& s, T& out) {
std::stringstream ss(s);
ss >> out;
}
#endif


/// @brief Specialization for string.
Expand Down Expand Up @@ -360,13 +373,28 @@ inline void JParameterManager::Parse(const std::string& value, std::vector<T> &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 <typename T>
inline std::string JParameterManager::Stringify(const T& value) {
constexpr bool serializable = JTypeInfo::is_serializable<T>::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 <typename T>
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) {
Expand Down
28 changes: 6 additions & 22 deletions src/programs/tests/JParameterManagerTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -402,32 +402,16 @@ TEST_CASE("JParameterManager_Issue217StringsWithWhitespace") {
}
}

#if __cplusplus >= 201703L
template <typename T>
void fakeParse(std::string s, T& out) {
constexpr bool parseable = JTypeInfo::is_parseable<T>::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 <typename T>
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);
}


Expand Down

0 comments on commit 1abda35

Please sign in to comment.