为什么这个 constexpr 函数给我错误?
Why is this constexpr-function giving me errors?
出于调试目的,我希望能够将类型的名称作为字符串获取,经过一番谷歌搜索后,我在 SO 上找到了这个答案:
C++ Get name of type in template
它提出了这个解决方案:
#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>();
}
答案的得分为 10,因此我认为该代码适用于大多数人,但目前我在尝试 运行 时遇到错误。
Error C2131 expression did not evaluate to a constant
指向行 inline static constexpr RawTypeNameFormat format =
和
Error (active) E1763 a lambda is not allowed in a constant expression
指向行 []{
,就在第一个错误的行下方。
是什么导致了这些错误?是不是我的编译器对于这些功能来说太旧了?
示例代码仅 运行C++17 或更高版本。
您似乎正在使用 Visual Studio。如果是这样,您可以转到 Project Protities
并进行以下更改以使您的代码 运行 正确。
出于调试目的,我希望能够将类型的名称作为字符串获取,经过一番谷歌搜索后,我在 SO 上找到了这个答案:
C++ Get name of type in template
它提出了这个解决方案:
#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>();
}
答案的得分为 10,因此我认为该代码适用于大多数人,但目前我在尝试 运行 时遇到错误。
Error C2131 expression did not evaluate to a constant
指向行 inline static constexpr RawTypeNameFormat format =
和
Error (active) E1763 a lambda is not allowed in a constant expression
指向行 []{
,就在第一个错误的行下方。
是什么导致了这些错误?是不是我的编译器对于这些功能来说太旧了?
示例代码仅 运行C++17 或更高版本。
您似乎正在使用 Visual Studio。如果是这样,您可以转到 Project Protities
并进行以下更改以使您的代码 运行 正确。