宏获取最新的命名空间和函数名(而不是完整的签名)? [英] Macro to obtain current namespace and function name (but not full signature)?
问题描述
有没有获得当前的命名空间和功能名称的C ++宏?例如:
命名空间富{
命名空间吧{
无效巴兹(INT I,双D){
性病::法院LT&;<万家乐<<的std :: ENDL;
}
}
}
将打印 :: foo的酒吧::巴兹
。我知道的__ __功能
,但它不给的命名空间。和 BOOST_CURRENT_FUNCTION
给整个签名,含。参数和返回值类型:
无效美孚::酒吧::巴兹(INT,双)
也许,它是可以编写提取从 BOOST_CURRENT_FUNCTION
命名空间和函数名的宏?
我想,对于日志记录,得到一个记录字符串像
:: foo的酒吧::巴兹 - 嗒嗒日志消息等等
据我所知,这是不可能的(可移植没有)。然而,从完整的签名就可以的提取物的这些参数。当然,这需要分析说,签名......这不是那么容易:X
下面是我目前使用的功能:
//我们想消费什么:
//无效
//符号短
//无符号整型
//测试::酒吧< T,N>
//
静态字符常量* consumeType(字符常量* const的开始,字符常量* const的结束){
静态常量StringRef签名(签名);
静态常量StringRef无符号(符号); 字符常量* IT =开始; 如果(startsWith(它,签名)){这+ = Signed.size()+ 1; }
否则,如果(startsWith(它,无符号)){这+ = Unsigned.size()+ 1; } //跳过的返回类型
为size_t templateNest = 0;
而(它!=结束){
如果(*它==''和templateNest == 0){打破; }
如果(*它=='<'){++ templateNest; }
如果(*它=='>'和templateNest大于0){--templateNest; } ++它;
} 把它返还;
} // consumeType//
// \\参数签名:签名通过GCC __func___返回
// \\回报:全名,包括名字空间限定符和类(如果有的话)
//
//无效的Test ::酒吧< T,N> ::参数(U)常量
// [与unsigned int类型O = 4U,U =测试::美孚,
// T =测试::富,无符号整型N = 3U]
// - >测试::酒吧< T,N> ::参数
//
StringRef parseFunctionName(StringRef const的签名){
字符常量*开始= signature.begin();
字符常量*结束= signature.end(); //跃过返回类型
开始= consumeType(开始,结束);
如果(开始==结束){返回签名; } //返回类型之后跳过空间
++开始;
如果(开始==结束){返回签名; } //如果我们遇到一个'('那么就意味着我们返回的函数,
//我们再次需要跳过的返回类型
如果(*开始=='('){
开始= consumeType(++开始,结束); //跳过空间
++开始;
如果(开始==结束){返回签名; }
} //最后,我们得到的开始,我们需要得到结束,这是
//第一开口(
字符常量* E =的std ::找到(开始,结束,'(');
返回StringRef(开始,电子 - 开始);
} // parseFunctionName
和其accompagnying测试:
的#define UT_FUNCTION_CHECK(Signature_,名_)\\
UT_CHECK(parseFunctionName(StringRef(Signature_))==名_);void函数(){
//常规功能
UT_FUNCTION_CHECK(INT主要(),主)
UT_FUNCTION_CHECK(INT美孚(INT,双),富)
UT_FUNCTION_CHECK(无符号整型美孚(INT,双),富) //模板
UT_FUNCTION_CHECK(unsigned int类型的Test ::酒吧< T,N> ::打印()const的
[和T =测试::富,无符号整型N = 3U],
测试::酒吧< T,N> ::打印)
UT_FUNCTION_CHECK(测试::酒吧< T,N>的Test ::酒吧< T,N> ::打印()const的
[和T =测试::富,无符号整型N = 3U],
测试::酒吧< T,N> ::打印)
UT_FUNCTION_CHECK(无效的Test ::酒吧< T,N> ::参数(U)常量
[与unsigned int类型O = 4U,U =测试::美孚
T =测试::富,无符号整型N = 3U],
测试::酒吧< T,N> ::参数) //函数返回功能
UT_FUNCTION_CHECK(无效(*测试::富:: FUNC()const的)(),
测试::富:: FUNC)
UT_FUNCTION_CHECK(无效(测试::富:: *测试::富::方法()const的)(INT)善变,
测试::富::法)
UT_FUNCTION_CHECK(无效(测试::富:: *测试::富::超())
(无效(测试::富:: *)(int)的挥发性)常量
测试::富::超级)
} //功能
它的工作原理结合gcc的 __ __ FUNC
宏。
的 StringRef
类是类似的 LLVM :: StringRef
。
我想应该包括你的需要,如果你能负担得起额外的解析。这是相当快:无回溯,也没有动态分配,所以不应该是一个问题(特别是相对于写入文件...)
希望它帮助。
Is there a C++ macro that obtains the current namespace and function name? Example:
namespace foo {
namespace bar {
void baz(int i, double d) {
std::cout << MACRO << std::endl;
}
}
}
would print foo::bar::baz
. I know of __FUNCTION__
but it doesn't give the namespace. And BOOST_CURRENT_FUNCTION
gives the whole signature, incl. arguments and return type:
void foo::bar::baz(int, double)
Maybe, is it possible to write a macro that extracts the namespace and function name from BOOST_CURRENT_FUNCTION
?
I want that for logging purposes, to get a logging string like
foo::bar::baz -- blah logging message blah
As far as I know, it's not possible (not portably). However from the full signature you can extract those arguments. Of course it requires parsing said signature... which is not so easy :x
Here is the function I use at the moment:
// What we want to consume:
// void
// signed short
// unsigned int
// Test::Bar<T, N>
//
static char const* consumeType(char const* const begin, char const* const end){
static StringRef const Signed("signed");
static StringRef const Unsigned("unsigned");
char const* it = begin;
if (startsWith(it, Signed)) { it += Signed.size() + 1; }
else if (startsWith(it, Unsigned)) { it += Unsigned.size() + 1; }
// jump over the return type
size_t templateNest = 0;
while (it != end) {
if (*it == ' ' and templateNest == 0) { break; }
if (*it == '<') { ++templateNest; }
if (*it == '>' and templateNest > 0) { --templateNest; }
++it;
}
return it;
} // consumeType
//
// \param signature: signature as returned by __func___ on gcc
// \return: full name, included namespace qualifier and class (if any)
//
// void Test::Bar<T, N>::parameterized(U) const
// [with unsigned int O = 4u, U = Test::Foo,
// T = Test::Foo, unsigned int N = 3u]
// -> Test::Bar<T, N>::parameterized
//
StringRef parseFunctionName(StringRef const signature) {
char const* begin = signature.begin();
char const* end = signature.end();
// Jump over the return type
begin = consumeType(begin, end);
if (begin == end) { return signature; }
// skip the space right after the return type
++begin;
if (begin == end) { return signature; }
// if we encounter a '(' then it means that we return a function,
// and we once again need to jump over the return type
if (*begin == '(') {
begin = consumeType(++begin, end);
// skip the space
++begin;
if (begin == end) { return signature; }
}
// and finally, we got the beginning, and we need to get the end, which is
// the first opening '('
char const* e = std::find(begin, end, '(');
return StringRef(begin, e - begin);
} // parseFunctionName
And its accompagnying tests:
#define UT_FUNCTION_CHECK(Signature_, Name_) \
UT_CHECK(parseFunctionName(StringRef(Signature_)) == Name_);
void Function() {
// Regular functions
UT_FUNCTION_CHECK("int main()", "main")
UT_FUNCTION_CHECK("int foo(int, double)", "foo")
UT_FUNCTION_CHECK("unsigned int foo(int, double)", "foo")
// Templates
UT_FUNCTION_CHECK("unsigned int Test::Bar<T, N>::print() const"
" [with T = Test::Foo, unsigned int N = 3u]",
"Test::Bar<T, N>::print")
UT_FUNCTION_CHECK("Test::Bar<T, N> Test::Bar<T, N>::print() const"
" [with T = Test::Foo, unsigned int N = 3u]",
"Test::Bar<T, N>::print")
UT_FUNCTION_CHECK("void Test::Bar<T, N>::parameterized(U) const"
" [with unsigned int O = 4u, U = Test::Foo,"
" T = Test::Foo, unsigned int N = 3u]",
"Test::Bar<T, N>::parameterized")
// Functions returning functions
UT_FUNCTION_CHECK("void (* Test::Foo::func() const)()",
"Test::Foo::func")
UT_FUNCTION_CHECK("void (Test::Foo::* Test::Foo::method() const)(int)volatile",
"Test::Foo::method")
UT_FUNCTION_CHECK("void (Test::Foo::* Test::Foo::super())"
"(void (Test::Foo::*)(int)volatile)const",
"Test::Foo::super")
} // Function
It works in combination with gcc's __func__
macro.
The StringRef
class is similar to llvm::StringRef
.
I think it should cover your needs if you can afford the extra parsing. It's quite fast: no backtracking and no dynamic allocation, so should not be an issue (especially compared to writing to a file...).
Hope it helps.
这篇关于宏获取最新的命名空间和函数名(而不是完整的签名)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!