Czy istnieje __CLASS__
makro w C++, który daje nazwę podobną do __FUNCTION__
makro klasy, który daje nazwę funkcjiCzy istnieje makro __CLASS__ w C++?
Odpowiedz
Najbliższy rzeczą jest to, aby zadzwonić typeid(your_class).name()
- ale to kompilator generuje specyficzny zniekształconej nazwy.
Aby go użyć klasa wewnątrz tylko typeid(*this).name()
Jeszcze nie. (Myślę, że gdzieś jest proponowane __class__
). Możesz także spróbować wyodrębnić część klasową z __PRETTY_FUNCTION__
.
Jeśli mówisz MS C++ (Należy stwierdzić, esp jako __FUNCTION__
jest niestandardowym rozszerzeniem), istnieją __FUNCDNAME__
and __FUNCSIG__
symbols które można analizować
Jeśli kompilator bywa g++
i prosicie __CLASS__
, ponieważ chcesz uzyskać aktualną nazwę metody, w tym klasę, powinna pomóc __PRETTY_FUNCTION__
(zgodnie z info gcc
, sekcja 5.43 Nazwy funkcji jako ciągi znaków).
Problem z używaniem typeid(*this).name()
polega na tym, że w statycznym wywołaniu metody nie ma wskaźnika this
. Makro __PRETTY_FUNCTION__
zgłasza nazwę klasy w funkcjach statycznych, a także wywołania metod. Będzie to jednak działać tylko z gcc.
Oto przykład wyodrębniania informacji za pomocą interfejsu w stylu makra.
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__)
Makro __METHOD_NAME__
zwróci ciąg postaci <class>::<method>()
, przycinanie zwracany typ, modyfikatory i argumenty z tego co __PRETTY_FUNCTION__
daje.
czegoś, co wydobywa tylko nazwę klasy, niektóre należy zwrócić uwagę na sytuacje pułapki, gdzie nie ma klasy:
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__)
nie powinieneś otoczyć ten z '#ifdef __GNU_C__'? – einpoklum
zamiast' substr (0, dwukropkami) .rfind (”„) '' można użyć rfind (””, dwukropek) 'oszczędzić tworem dodatkowy strunowy. – mariusm
Wolałbym używać find_last_of ("::") W przeciwnym razie funkcja zwróci tylko przestrzeń nazw, jeśli istnieje jedna – underdoeg
myślę użyciu __PRETTY_FUNCTION__
jest wystarczająco dobry, choć zawiera nazw, jak również tj namespace::classname::functionname
aż __CLASS__
jest dostępny.
Możesz uzyskać nazwę funkcji wraz z nazwą klasy. To może przetwarzać funkcje typu C.
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) + "()";
}
Moje rozwiązanie:
std::string getClassName(const char* fullFuncName)
{
std::string fullFuncNameStr(fullFuncName);
size_t pos = fullFuncNameStr.find_last_of("::");
if (pos == std::string::npos)
{
return "";
}
return fullFuncNameStr.substr(0, pos-1);
}
#define __CLASS__ getClassName(__FUNCTION__)
ja pracuje dla Visual C++ 12.
Oto rozwiązanie oparte na __FUNCTION__
szablonów makr i C++:
template <class T>
class ClassName
{
public:
static std::string Get()
{
// Get function name, which is "ClassName<class T>::Get"
// The template parameter 'T' is the class name we're looking for
std::string name = __FUNCTION__;
// Remove "ClassName<class " ("<class " is 7 characters long)
size_t pos = name.find_first_of('<');
if (pos != std::string::npos)
name = name.substr(pos + 7);
// Remove ">::Get"
pos = name.find_last_of('>');
if (pos != std::string::npos)
name = name.substr(0, pos);
return name;
}
};
template <class T>
std::string GetClassName(const T* _this = NULL)
{
return ClassName<T>::Get();
}
Oto przykład jak to może być wykorzystane dla klasy rejestratora
template <class T>
class Logger
{
public:
void Log(int value)
{
std::cout << GetClassName<T>() << ": " << value << std::endl;
std::cout << GetClassName(this) << ": " << value << std::endl;
}
};
class Example : protected Logger<Example>
{
public:
void Run()
{
Log(0);
}
}
Wyjście Example::Run
będzie wtedy
Example: 0
Logger<Example>: 0
Pamiętaj, że nie uwzględnisz polimorfizmu, jeśli masz wskaźnik do bazy (co prawdopodobnie jest w porządku). –
To działa całkiem nieźle, jeśli jesteś gotów zapłacić koszt wskaźnika.
class State
{
public:
State(const char* const stateName) :mStateName(stateName) {};
const char* const GetName(void) { return mStateName; }
private:
const char * const mStateName;
};
class ClientStateConnected
: public State
{
public:
ClientStateConnected(void) : State(__FUNCTION__) {};
};
chciałbym sugerować boost::typeindex, którą poznałem od Scotta Meyera "skutecznych, nowoczesnych C++" Oto prosty przykład:
Przykład
#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";
}
Zestawione z „g ++ - -std = C++ 14" to produkuje następujące
Output
Jeśli chcesz wydrukować typ szablonu, to proste.
T = podwójny
Aby dostać od instancji obiektu, wystarczy użyć decltype: typ
FB jest: foo_bar
Czy można w ten sposób uzyskać nazwę klasy bez przestrzeni nazw? aka http://coliru.stacked-crooked.com/a/cf1b1a865bb7ecc7 – tower120
Works z MSVC i GCC zbyt
#ifdef _MSC_VER
#define __class_func__ __FUNCTION__
#endif
#ifdef __GNUG__
#include <cxxabi.h>
#include <execinfo.h>
char *class_func(const char *c, const char *f)
{
int status;
static char buff[100];
char *demangled = abi::__cxa_demangle(c, NULL, NULL, &status);
snprintf(buff, sizeof(buff), "%s::%s", demangled, f);
free(demangled);
return buff;
}
#define __class_func__ class_func(typeid(*this).name(), __func__)
#endif
następującej metody (na podstawie methodName) (powyżej) mogą również obsługiwać wejściowych, takich jak "int głównym (int ARGC char ** argv)":
string getMethodName(const string& prettyFunction)
{
size_t end = prettyFunction.find("(") - 1;
size_t begin = prettyFunction.substr(0, end).rfind(" ") + 1;
return prettyFunction.substr(begin, end - begin + 1) + "()";
}
- 1. Jak sprawdzić, czy makro istnieje w CMake
- 2. Czy istnieje makro LARGEST_INTEGER lub coś podobnego? (C)
- 3. "z" makro w C
- 4. Zamknięcia nad __class__
- 5. Przecinek w C/C++ makro
- 6. Czy istnieje sposób, aby sprawdzić, czy wartości nie numerycznej makro
- 7. Preprocesor C: makro i makro makra stringi
- 8. C makro/# zdefiniować wcięcie?
- 9. C++ 11 predefiniowane makro
- 10. C++ szablonu makro skrót
- 11. Legit Zastosowania przesunięcia makro w C/C++
- 12. Makro redefinicja w C i C++
- 13. C/C++ #define Makro w makrze?
- 14. Czy istnieje sposób na usunięcie cudzysłowów w makrze C?
- 15. c zdefiniować makro multilinii?
- 16. C++: Czy makro może rozwinąć "abc" na "a", "b", "c"?
- 17. Czy istnieje odpowiednik statycznego C w C#?
- 18. Czy możemy napisać makro w języku C# dla Excela
- 19. Czy istnieje dekompilator C++?
- 20. C makro dla wykrywania wersji OS X (lew czy nie)?
- 21. Jak tymczasowo wyłączyć rozszerzenie makro w C/C++?
- 22. C makro: kontrola #if dla równości
- 23. zależny makro makro
- 24. Przepisywanie C++ makro jako funkcję itp
- 25. Właściwa C preprocesora makro no-op
- 26. C Konformacja makro tokenów ze zmienną - czy to możliwe?
- 27. Czy to makro ma zaletę?
- 28. Jak wykonać super() pracę, ręcznie wypełniając komórkę __class__?
- 29. Czy istnieje odpowiednik F # Seq.windowed w C#?
- 30. C++ Sprawdź, czy element istnieje w tablicy
Dzięki .. to jest wystarczająco dobry do rejestrowania – mortal
Trzeba wiedzieć, klasa pierwsza, aby wywołać tę ;-) –
służy do logowania, więc wiem klasę gdzie jestem powołując się to. Po prostu staramy się unikać jednoznacznie definiując tablicę char zawierający nazwę klasy – mortal