C++ 中是否有类似于 __FUNCTION__
宏用于获取函数名的 __CLASS__
宏,以获取类名?
使用typeid(*this).name()
的问题在于,在静态方法调用中没有this
指针。而宏__PRETTY_FUNCTION__
在静态函数和方法调用中都会报告类名。但是,这只适用于gcc。
这里是通过宏样式接口提取信息的示例。
inline std::string methodName(const std::string& prettyFunction)
{
size_t colons = prettyFunction.find("::");
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
size_t end = prettyFunction.rfind("(") - begin;
return prettyFunction.substr(begin,end) + "()";
}
#define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__)
宏__METHOD_NAME__
将返回一个字符串,格式为<class>::<method>()
,从__PRETTY_FUNCTION__
给出的内容中删除返回类型、修饰符和参数。
如果要提取类名,必须注意捕捉没有类的情况:
inline std::string className(const std::string& prettyFunction)
{
size_t colons = prettyFunction.find("::");
if (colons == std::string::npos)
return "::";
size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1;
size_t end = colons - begin;
return prettyFunction.substr(begin,end);
}
#define __CLASS_NAME__ className(__PRETTY_FUNCTION__)
最接近的称呼是调用 typeid(你的类).name()
- 但它会生成特定于编译器的名称混淆。
若要在类内使用,请使用 typeid(*this).name()
__func__
和非标准的__FUNCTION__
都不是宏。微软将__FUNCTION__
文档化为宏,但它不是真正的宏的明显特征是,在使用/P
编译时,它不会被预处理器展开。 - Steve Jessop目前还没有。(我认为在某个地方提出了__class__
)。您也可以尝试从 __PRETTY_FUNCTION__
中提取类部分。
#include <boost/type_index.hpp>
class foo_bar
{
int whatever;
};
namespace bti = boost::typeindex;
template <typename T>
void from_type(T t)
{
std::cout << "\tT = " << bti::type_id_with_cvr<T>().pretty_name() << "\n";
}
int main()
{
std::cout << "If you want to print a template type, that's easy.\n";
from_type(1.0);
std::cout << "To get it from an object instance, just use decltype:\n";
foo_bar fb;
std::cout << "\tfb's type is : "
<< bti::type_id_with_cvr<decltype(fb)>().pretty_name() << "\n";
}
我认为使用__PRETTY_FUNCTION__
已经足够好了,尽管它包括命名空间和类名,例如namespace::classname::functionname
,直到__CLASS__
可用。
如果您需要在编译时实际生成类名,可以使用C++11来完成此操作:
#define __CLASS__ std::remove_reference<decltype(classMacroImpl(this))>::type
template<class T> T& classMacroImpl(const T* t);
我知道这不是__FUNCTION__
的同义词,但我在寻找这样的答案时发现了这篇帖子。:D
我使用C++17 constexpr
和std::string_view
方法创建了一个函数,其中包含__PRETTY_FUNCTION__
。我还稍微更新了算法以使其更可靠。(感谢@n. 'pronouns' m在64387023中的帮助)。
constexpr std::string_view method_name(const char* s)
{
std::string_view prettyFunction(s);
size_t bracket = prettyFunction.rfind("(");
size_t space = prettyFunction.rfind(" ", bracket) + 1;
return prettyFunction.substr(space, bracket-space);
}
#define __METHOD_NAME__ method_name(__PRETTY_FUNCTION__)
在C++20中,可以将函数声明为consteval
,强制它在编译时评估。此外,还有std::basic_fixed_string
用作模板参数。
如果你的编译器是 g++
,并且你想要一种获取当前方法名(包括类名)的方式,那么使用 __PRETTY_FUNCTION__
应该会有帮助(根据 info gcc
的第 5.43节 函数名作为字符串)。
static std::string methodName(const std::string& prettyFunction)
{
size_t begin,end;
end = prettyFunction.find("(");
begin = prettyFunction.substr(0,end).rfind(" ") + 1;
end -= begin;
return prettyFunction.substr(begin,end) + "()";
}
#ifdef __GNU_C__
包围起来吗? - einpoklumrfind(' ', colons)
来避免创建额外的字符串,而不是substr(0,colons).rfind(" ")
。 - mariusm__METHOD_NAME__
宏的版本。请查看这里。 - Antonio