ein*_*ica 28 c++ reflection compile-time constexpr c++14
我想在编译时使用类型的名称.例如,假设我写了:
constexpr size_t my_strlen(const char* s)
{
const char* cp = s;
while(*cp != '\0') { cp++; };
return cp - s;
}
Run Code Online (Sandbox Code Playgroud)
现在我希望:
template <typename T>
constexpr auto type_name_length = my_strlen(typeid(T).name());
Run Code Online (Sandbox Code Playgroud)
但是,唉,typeid(T).name()只是const char*,而不是constexpr ......还有其他一些constexpr方法来获得一个类型的名字吗?
Jam*_*ree 70
嗯,你可以,但可能不太便携:
struct string_view
{
char const* data;
std::size_t size;
};
inline std::ostream& operator<<(std::ostream& o, string_view const& s)
{
return o.write(s.data, s.size);
}
template<class T>
constexpr string_view get_name()
{
char const* p = __PRETTY_FUNCTION__;
while (*p++ != '=');
for (; *p == ' '; ++p);
char const* p2 = p;
int count = 1;
for (;;++p2)
{
switch (*p2)
{
case '[':
++count;
break;
case ']':
--count;
if (!count)
return {p, std::size_t(p2 - p)};
}
}
return {};
}
Run Code Online (Sandbox Code Playgroud)
您可以将您想要的定义type_name_length为:
template <typename T>
constexpr auto type_name_length = get_name<T>().size;
Run Code Online (Sandbox Code Playgroud)
DEMO(适用于clang&g ++)
ein*_*ica 15
编辑:根据对非 constexpr 特定问题的答案进行更新;它是包括 @HowardHinnant、@\xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b @Val 和我自己在内的几个人改进的结果。
\n据我所知,语言标准没有提供任何获取类型名称的设施。因此,我们采用特定于编译器的方法。这适用于 GCC、clang 和 MSVC。
\n#include <string_view>\n// If you can\'t use C++17\'s standard library, you\'ll need to use the GSL \n// string_view or implement your own struct (which would not be very difficult,\n// since we only need a few methods here)\n\ntemplate <typename T> constexpr std::string_view type_name();\n\ntemplate <>\nconstexpr std::string_view type_name<void>()\n{ return "void"; }\n\nnamespace detail {\n\nusing type_name_prober = void;\n\ntemplate <typename T>\nconstexpr std::string_view wrapped_type_name() \n{\n#ifdef __clang__\n return __PRETTY_FUNCTION__;\n#elif defined(__GNUC__)\n return __PRETTY_FUNCTION__;\n#elif defined(_MSC_VER)\n return __FUNCSIG__;\n#else\n#error "Unsupported compiler"\n#endif\n}\n\nconstexpr std::size_t wrapped_type_name_prefix_length() { \n return wrapped_type_name<type_name_prober>().find(type_name<type_name_prober>()); \n}\n\nconstexpr std::size_t wrapped_type_name_suffix_length() { \n return wrapped_type_name<type_name_prober>().length() \n - wrapped_type_name_prefix_length() \n - type_name<type_name_prober>().length();\n}\n\n} // namespace detail\n\ntemplate <typename T>\nconstexpr std::string_view type_name() {\n constexpr auto wrapped_name = detail::wrapped_type_name<T>();\n constexpr auto prefix_length = detail::wrapped_type_name_prefix_length();\n constexpr auto suffix_length = detail::wrapped_type_name_suffix_length();\n constexpr auto type_name_length = wrapped_name.length() - prefix_length - suffix_length;\n return wrapped_name.substr(prefix_length, type_name_length);\n}\nRun Code Online (Sandbox Code Playgroud)\n