VariantVisitors: Template replace redundant code
There are a lot of cut-and-paste code blocks in VariantVisitors,
and much of the redundancy can be replaced by just using a template.
Also took the opportunity to improve the error message that is
thrown, when a type mismatch exception happens.
Tested: Works for me, no changes noted from previous behavior.
Signed-off-by: Josh Lehan <krellan@google.com>
Change-Id: I96b45dde7e2f6445082b3f69d66bf92d33eedf64
diff --git a/include/VariantVisitors.hpp b/include/VariantVisitors.hpp
index 6549a32..27185ca 100644
--- a/include/VariantVisitors.hpp
+++ b/include/VariantVisitors.hpp
@@ -15,49 +15,39 @@
*/
#pragma once
+#include <boost/type_index.hpp>
+
#include <stdexcept>
#include <string>
#include <variant>
-struct VariantToFloatVisitor
+namespace details
{
+template <typename U>
+struct VariantToNumericVisitor
+{
template <typename T>
- float operator()(const T& t) const
+ U operator()(const T& t) const
{
if constexpr (std::is_arithmetic_v<T>)
{
- return static_cast<float>(t);
+ return static_cast<U>(t);
}
- throw std::invalid_argument("Cannot translate type to float");
+ throw std::invalid_argument(
+ "Cannot translate type " +
+ boost::typeindex::type_id<T>().pretty_name() + " to " +
+ boost::typeindex::type_id<U>().pretty_name());
}
};
-struct VariantToIntVisitor
-{
- template <typename T>
- int operator()(const T& t) const
- {
- if constexpr (std::is_arithmetic_v<T>)
- {
- return static_cast<int>(t);
- }
- throw std::invalid_argument("Cannot translate type to int");
- }
-};
+} // namespace details
-struct VariantToUnsignedIntVisitor
-{
- template <typename T>
- unsigned int operator()(const T& t) const
- {
- if constexpr (std::is_arithmetic_v<T>)
- {
- return static_cast<unsigned int>(t);
- }
- throw std::invalid_argument("Cannot translate type to unsigned int");
- }
-};
+using VariantToFloatVisitor = details::VariantToNumericVisitor<float>;
+using VariantToIntVisitor = details::VariantToNumericVisitor<int>;
+using VariantToUnsignedIntVisitor =
+ details::VariantToNumericVisitor<unsigned int>;
+using VariantToDoubleVisitor = details::VariantToNumericVisitor<double>;
struct VariantToStringVisitor
{
@@ -72,19 +62,8 @@
{
return std::to_string(t);
}
- throw std::invalid_argument("Cannot translate type to string");
- }
-};
-
-struct VariantToDoubleVisitor
-{
- template <typename T>
- double operator()(const T& t) const
- {
- if constexpr (std::is_arithmetic_v<T>)
- {
- return static_cast<double>(t);
- }
- throw std::invalid_argument("Cannot translate type to double");
+ throw std::invalid_argument(
+ "Cannot translate type " +
+ boost::typeindex::type_id<T>().pretty_name() + " to string");
}
};