make UniversalPrinter<std::any> support RTTI

This commit is contained in:
Krystian Kuzniarek 2020-03-07 17:25:51 +01:00
parent c7858b7f33
commit 5ac7646e96
3 changed files with 46 additions and 21 deletions

View File

@ -688,13 +688,20 @@ class UniversalPrinter<Any> {
public: public:
static void Print(const Any& value, ::std::ostream* os) { static void Print(const Any& value, ::std::ostream* os) {
if (value.has_value()) if (value.has_value())
*os << "'any' type with value of type " << GetTypeName(); *os << "'any' type with value of type " << GetTypeName(value);
else else
*os << "'any' type with no value"; *os << "'any' type with no value";
} }
private: private:
static std::string GetTypeName() { return "the element type"; } static std::string GetTypeName(const Any& value) {
#if GTEST_HAS_RTTI
return internal::GetTypeName(value.type());
#else
static_cast<void>(value); // possibly unused
return "the element type";
#endif // GTEST_HAS_RTTI
}
}; };
#endif // GTEST_INTERNAL_HAS_ANY #endif // GTEST_INTERNAL_HAS_ANY

View File

@ -64,34 +64,40 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
return s; return s;
} }
// GetTypeName<T>() returns a human-readable name of type T. #if GTEST_HAS_RTTI
// GetTypeName(const std::type_info&) returns a human-readable name of type T.
// NB: This function is also used in Google Mock, so don't move it inside of // NB: This function is also used in Google Mock, so don't move it inside of
// the typed-test-only section below. // the typed-test-only section below.
template <typename T> inline std::string GetTypeName(const std::type_info& type) {
std::string GetTypeName() { const char* const name = type.name();
# if GTEST_HAS_RTTI #if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
const char* const name = typeid(T).name();
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
int status = 0; int status = 0;
// gcc's implementation of typeid(T).name() mangles the type name, // gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it. // so we have to demangle it.
# if GTEST_HAS_CXXABI_H_ #if GTEST_HAS_CXXABI_H_
using abi::__cxa_demangle; using abi::__cxa_demangle;
# endif // GTEST_HAS_CXXABI_H_ #endif // GTEST_HAS_CXXABI_H_
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
const std::string name_str(status == 0 ? readable_name : name); const std::string name_str(status == 0 ? readable_name : name);
free(readable_name); free(readable_name);
return CanonicalizeForStdLibVersioning(name_str); return CanonicalizeForStdLibVersioning(name_str);
# else #else
return name; return name;
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC #endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
}
# else #endif // GTEST_HAS_RTTI
// GetTypeName<T>() returns a human-readable name of type T if and only if
// RTTI is enabled, otherwise it returns a dummy type name.
// NB: This function is also used in Google Mock, so don't move it inside of
// the typed-test-only section below.
template <typename T>
std::string GetTypeName() {
#if GTEST_HAS_RTTI
return GetTypeName(typeid(T));
#else
return "<type>"; return "<type>";
#endif // GTEST_HAS_RTTI
# endif // GTEST_HAS_RTTI
} }
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P

View File

@ -1532,22 +1532,34 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
} }
#if GTEST_INTERNAL_HAS_ANY #if GTEST_INTERNAL_HAS_ANY
TEST(PrintAnyTest, Empty) { class PrintAnyTest : public ::testing::Test {
protected:
template <typename T>
static std::string ExpectedTypeName() {
#if GTEST_HAS_RTTI
return internal::GetTypeName<T>();
#else
return "the element type";
#endif // GTEST_HAS_RTTI
}
};
TEST_F(PrintAnyTest, Empty) {
internal::Any any; internal::Any any;
EXPECT_EQ("'any' type with no value", PrintToString(any)); EXPECT_EQ("'any' type with no value", PrintToString(any));
} }
TEST(PrintAnyTest, NonEmpty) { TEST_F(PrintAnyTest, NonEmpty) {
internal::Any any; internal::Any any;
constexpr int val1 = 10; constexpr int val1 = 10;
const std::string val2 = "content"; const std::string val2 = "content";
any = val1; any = val1;
EXPECT_EQ("'any' type with value of type the element type", EXPECT_EQ("'any' type with value of type " + ExpectedTypeName<int>(),
PrintToString(any)); PrintToString(any));
any = val2; any = val2;
EXPECT_EQ("'any' type with value of type the element type", EXPECT_EQ("'any' type with value of type " + ExpectedTypeName<std::string>(),
PrintToString(any)); PrintToString(any));
} }
#endif // GTEST_INTERNAL_HAS_ANY #endif // GTEST_INTERNAL_HAS_ANY