a 的名称本身无法在不使用非 C++ 正式组成部分的功能的情况下以任何方式访问。如果您想保持符合标准,您将别无选择,只能手动填写该部分。
除此之外,如果您可以访问<cxxabi.h>,则可以使用typeid() 和abi::__cxa_demangle 填写其余部分,但此时您必须在运行时开始连接字符串,这不是很好,但它确实让你接近你想去的地方。
#include <typeinfo>
#include <string>
#include <iostream>
#include <memory>
#include <cxxabi.h>
template<typename T>
std::string member_name(const char* name) {
int status = 0;
auto type_name = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
// Feel free to return an error string instead of throwing an exception, obviously...
if(status != 0) throw std::runtime_error("failed to lookup type name");
std::unique_ptr<char, void(*)(void*)> cleanup(type_name, std::free);
return std::string(type_name) + "::a";
}
namespace example {
class Test {
public:
int a;
static std::string a_name() {
return member_name<Test>("a");
}
};
}
int main() {
std::cout << example::Test::a_name() << "\n";
}
编辑:
如果您愿意跳出标准 C++ 的界限,那么您可以使用编译器特定的宏和一些 constexpr 与 std::string_view 的配合来在编译时获取成员名称。
这改编自C++ Get name of type in template 提出的解决方案(感谢@HolyBlackCat!)
#include <string_view>
#include <iostream>
namespace detail {
struct Placeholder {
int member;
};
template<auto T>
constexpr std::string_view raw_member_name() {
#ifdef _MSC_VER
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
}
constexpr std::pair<std::size_t, std::size_t> member_name_offsets() {
std::string_view raw = raw_member_name<&Placeholder::member>();
std::string_view lookup = "detail::Placeholder::member";
auto leading = raw.find(lookup);
auto trailing = raw.size() - lookup.size();
return {leading, trailing};
}
}
template<auto T>
constexpr std::string_view member_name() {
constexpr auto offsets = detail::member_name_offsets();
std::string_view pretty = detail::raw_member_name<T>();
return pretty.substr(offsets.first, pretty.size() - offsets.second);
}
namespace example {
class Test {
public:
int a;
static constexpr auto a_name = member_name<&Test::a>();
};
}
int main() {
std::cout << example::Test::a_name << "\n"; // outputs: "example::Test::a"
}
如果您绝对必须有一个以 null 结尾的字符串,您还必须将字节复制到 std::array<char, L+1> 中。