developer tip

C ++에 __CLASS__ 매크로가 있습니까?

optionbox 2020. 9. 14. 08:19
반응형

C ++에 __CLASS__ 매크로가 있습니까?


함수 이름을 제공하는 매크로 __CLASS__와 유사한 클래스 이름을 제공하는 C ++에 매크로 가 있습니까?__FUNCTION__


가장 가까운 것은 호출하는 것입니다 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>()반환하여 반환 유형, 수정 자 및 인수를 __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__.


나는 Scott Meyer의 "Effective Modern C ++"에서 배운 boost :: typeindex 를 제안 하고 싶습니다. 다음은 기본적인 예입니다.

#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 = 이중

객체 인스턴스에서 가져 오려면 decltype을 사용하십시오.

fb의 유형 : foo_bar


나는 사용할 수 있을 때까지 __PRETTY_FUNCTION__네임 스페이스도 포함하지만 사용하면 충분 하다고 생각 합니다.namespace::classname::functionname__CLASS__


If your compiler happens to be g++ and you are asking for __CLASS__ because you want a way to get the current method name including the class, __PRETTY_FUNCTION__ should help (according to info gcc, section 5.43 Function Names as Strings).


If you're talking MS C++ (You should state, esp as __FUNCTION__ is a non-standard extension), there are __FUNCDNAME__ and __FUNCSIG__ symbols which you could parse


You can get the function name including class name. This can process C-type funcitons.

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) + "()";
}

My solution:

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__)

I works for Visual C++ 12.


Here's a solution based on the __FUNCTION__ macro and C++ templates:

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();
}

Here's an example of how this could be used for a logger class

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);
  }
}

The output of Example::Run will then be

Example: 0
Logger<Example>: 0

If you need something that will actually produce the class name at compile time, you can use C++11 to do this:

#define __CLASS__ std::remove_reference<decltype(classMacroImpl(this))>::type

template<class T> T& classMacroImpl(const T* t);

I recognize that this is not the same thing as __FUNCTION__ but I found this post while looking for an answer like this. :D


This works quite nicely if you are willing to pay the cost of a pointer.

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__ ) {};
};

Works with msvc and gcc too

#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

Following method (based on methodName() above) can also handle input like "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) + "()";
}

참고URL : https://stackoverflow.com/questions/1666802/is-there-a-class-macro-in-c

반응형