Consider:
#include <iostream>
#include <typeinfo>
#include <type_traits>
#include <cxxabi.h>
#include <boost/hana.hpp>
namespace hana = boost::hana;
struct Person {
BOOST_HANA_DEFINE_STRUCT(Person,
(std::string, name),
(int, age)
);
};
template<typename T>
void stringify(const T& v) {
hana::for_each(hana::accessors<T>(), [&v](auto a) {
// Here I'm printing the demangled type, just to make sure it is actually the type I'm thinking it is.
std::cout << abi::__cxa_demangle(typeid(decltype(hana::second(a)(v)){}).name(), 0, 0, 0);
// If the value is arithmetic, "quote" should be an empty string. Else, it should be an actual quote.
// UNEXPECTED BEHAVIOR IS HERE
std::string quote{(std::is_arithmetic<decltype(hana::second(a)(v))>::value?"":"\"")};
// Finally do what we're here for.
std::cout << " " << hana::first(a).c_str() << " = " << quote << hana::second(a)(v) << quote << "\n";
});
}
int main() {
Person john;
john.name = "John Doe";
john.age = 42;
stringify(john);
}
Output:
std::__cxx11::basic_string</*...*/> name = "John Doe"
int age = "42"
I'm trying to use std::is_arithmetic
to tell if I'm dealing with a number instead of some other non-arithmetic type, and print (or not) a quote accordingly.
But for some reason, the value being "returned" (through ::value
member) is false
, even though I'm passing an int
(I make sure I'm doing that right by first printing the demangled type using gcc's cxxabi.h
)
As you can see from the output, this causes the int
to be printed with quotes.
My question(s) is: why is it returning false? Does this have anything to do with the generic lambda? Can I fix it?
I'm actually testing this directly on Coliru, so you can assume whatever gcc version used there (Currently 6.3.0).
Your problem is that in spite of the type typeid
returns (int) your actual type inside the lambda is int const&
and is_arithmetic
is not specialized for that exact type. You can get the type you actually want with std::decay
or a combination of std::remove_const
and std::remove_reference
.