0

For debug purposes, I want to be able to get the name of a type as a string, and after some Googling I found this answer on SO:

C++ Get name of type in template

It presents this solution:

#include <array>
#include <cstddef>

namespace impl
{
    template <typename T>
    constexpr const auto &RawTypeName()
    {
        #ifdef _MSC_VER
        return __FUNCSIG__;
        #else
        return __PRETTY_FUNCTION__;
        #endif
    }

    struct RawTypeNameFormat
    {
        std::size_t leading_junk = 0, trailing_junk = 0;
    };

    // Returns `false` on failure.
    inline constexpr bool GetRawTypeNameFormat(RawTypeNameFormat *format)
    {
        const auto &str = RawTypeName<int>();
        for (std::size_t i = 0;; i++)
        {
            if (str[i] == 'i' && str[i+1] == 'n' && str[i+2] == 't')
            {
                if (format)
                {
                    format->leading_junk = i;
                    format->trailing_junk = sizeof(str)-i-3-1; // `3` is the length of "int", `1` is the space for the null terminator.
                }
                return true;
            }
        }
        return false;
    }

    static constexpr RawTypeNameFormat format =
    []{
        static_assert(GetRawTypeNameFormat(nullptr), "Unable to figure out how to generate type names on this compiler.");
        RawTypeNameFormat format;
        GetRawTypeNameFormat(&format);
        return format;
    }();
}

// Returns the type name in a `std::array<char, N>` (null-terminated).
template <typename T>
[[nodiscard]] constexpr auto CexprTypeName()
{
    constexpr std::size_t len = sizeof(impl::RawTypeName<T>()) - impl::format.leading_junk - impl::format.trailing_junk;
    std::array<char, len> name{};
    for (std::size_t i = 0; i < len-1; i++)
        name[i] = impl::RawTypeName<T>()[i + impl::format.leading_junk];
    return name;
}

template <typename T>
[[nodiscard]] const char *TypeName()
{
    static constexpr auto name = CexprTypeName<T>();
    return name.data();
}
template <typename T>
[[nodiscard]] const char *TypeName(const T &)
{
    return TypeName<T>();
}

The answer has a score of ten so I assume the code works for most people, but I currently get errors when I try to run it.

Error C2131 expression did not evaluate to a constant that points to the line inline static constexpr RawTypeNameFormat format =

and

Error (active) E1763 a lambda is not allowed in a constant expression that points to the line []{, right under the line with the first error.

What is causing these errors? Is it that my compiler is too old for these features?

2
  • What's your compiler's version? It works with msvc 19 :godbolt.org/z/19f4aG6so Commented Jun 20, 2021 at 9:43
  • @prehistoricpenguin I'm unsure. How do I check what compiler I'm using in Visual Studio? Commented Jun 20, 2021 at 10:03

1 Answer 1

1

The sample code only runs with C++17 or higher.

It seems that you are using Visual Studio. And if so, you can go to the Project Protities and do the following change to make your code run properly.

2021-06-20_00.png

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.