Есть ли макрос класса В C++?
есть __CLASS__
макрос в C++, который дает имя класса, похожее на __FUNCTION__
макрос, который дает имя функции
14 ответов:
самое близкое, что есть-назвать
typeid(your_class).name()
- но это создает компилятор конкретного искаженного имени.использовать его внутри класса просто
typeid(*this).name()
проблема с использованием
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>()
, обрезка возвращаемого типа, модификаторов и аргументов из what__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__)
пока нет. (Я думаю
__class__
предлагается где-то). Вы также можете попробовать извлечь часть класса из__PRETTY_FUNCTION__
.
Я хотел бы предложить boost:: typeindex, о котором я узнал из "эффективного современного C++" Скотта Мейера вот основной пример:
пример
#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"; }
скомпилированный с "g++ -- std=c++14" это производит следующее
выход
Если вы хотите напечатать тип шаблона, это легко.
T = double
чтобы получить его из экземпляра объекта, просто использовать decltype:
тип fb: foo_bar
Я думаю, что с помощью
__PRETTY_FUNCTION__
достаточно хорошо, хотя он также включает пространство имен, т. е.namespace::classname::functionname
до__CLASS__
доступно.
если ваш компилятор бывает
g++
а ты просишь__CLASS__
потому что вы хотите способ получить текущее имя метода, включая класс,__PRETTY_FUNCTION__
должно помочь (по даннымinfo gcc
, раздел 5.43 имена функций в виде строк).
Если вы говорите MS C++ (вы должны заявить, esp как
__FUNCTION__
это нестандартное расширение), есть__FUNCDNAME__
и__FUNCSIG__
символы который вы могли разобрать
вы можете получить имя функции, включая имя класса. Это может обрабатывать функции 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) + "()"; }
мое решение:
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__)
Я работаю для Visual C++ 12.
вот решение, основанное на
__FUNCTION__
макро и 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(); }
вот пример того, как это может быть использовано для класса регистратора
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); } }
выход
Example::Run
то будетExample: 0 Logger<Example>: 0
Если вам нужно что-то, что будет фактически производить имя класса во время компиляции, вы можете использовать C++11 для этого:
#define __CLASS__ std::remove_reference<decltype(classMacroImpl(this))>::type template<class T> T& classMacroImpl(const T* t);
Я признаю, что это не то же самое как
__FUNCTION__
но я нашел этот пост, ища такой ответ. : D
это работает довольно хорошо, если вы готовы оплатить стоимость указатель.
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__ ) {}; };
работает с msvc и gcc тоже
#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
следующий метод (основанный на methodName() выше) также может обрабатывать входные данные, такие как"int main(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) + "()"; }