एक प्रवेश स्ट्रिंग पाने के लिए जहां तक मैं जानता हूँ कि चाहते हैं, यह संभव नहीं है (नहीं portably)। हालांकि पूर्ण हस्ताक्षर से आप उन तर्कों को निकाल सकते हैं। बेशक यह पार्स हस्ताक्षर कहा की आवश्यकता है ... जो इतना आसान नहीं है:
// 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
और इसकी accompagnying परीक्षण:
#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
एक्स
यहाँ समारोह मैं इस समय का उपयोग है यह जीसीसी के __func__
मैक्रो के संयोजन में काम करता है।
StringRef
कक्षा llvm::StringRef
के समान है।
मुझे लगता है कि यदि आप अतिरिक्त पार्सिंग का जोखिम उठा सकते हैं तो मुझे आपकी ज़रूरतों को पूरा करना चाहिए। यह काफी तेज़ है: कोई बैकट्रैकिंग और गतिशील आवंटन नहीं, इसलिए कोई समस्या नहीं होनी चाहिए (विशेष रूप से फ़ाइल में लिखने की तुलना में ...)।
उम्मीद है कि यह मदद करता है।
मुझे नहीं लगता कि फ़ंक्शन के पूर्ण हस्ताक्षर प्राप्त करने के लिए कोई प्लेटफार्म स्वतंत्र तरीका है। हालांकि, आप '__FILE__' और' __LINE__' के कॉम्बो का उपयोग क्यों नहीं कर सकते? यह आपको लगभग एक ही प्रभाव देगा; इसके अलावा एक फ़ंक्शन खोजने की तुलना में लॉग से आपके कोड में ढूंढने के लिए तेज़ है! – iammilind
@iammilind: दरअसल, मैं log4cxx में लॉगर नाम के रूप में मैक्रो सामग्री का उपयोग करना चाहता हूं। उन लॉगर नाम पदानुक्रमित हैं और आप अलग-अलग नामस्थानों के लिए अलग-अलग लॉग स्तर सेट कर सकते हैं, इसलिए मैं वास्तव में क्या करता हूं जैसे 'log4cxx :: LoggerPtr लॉगर (log4cxx :: लॉगर :: getLogger ("foo.bar.baz")) ; LOG4CXX_INFO (लॉगर, "ब्ला लॉगिंग संदेश ब्लाह"); 'मैक्रो को' foo.bar.baz' भाग भरना चाहिए। मैं इसे अपनी पोस्ट में जटिल बनाना नहीं चाहता था। – Frank