Y a t-il __CLASS__
macro en C++ qui donne un nom de classe similaire à __FUNCTION__
macro donnant le nom de la fonction
Le plus proche consiste à appeler typeid(your_class).name()
- mais cela produit un nom mutilé spécifique au compilateur.
Pour l'utiliser à l'intérieur de la classe, il suffit de typeid(*this).name()
Le problème avec l'utilisation de typeid(*this).name()
est qu'il n'y a pas de pointeur this
dans un appel de méthode statique. La macro __PRETTY_FUNCTION__
Indique un nom de classe dans les fonctions statiques ainsi que dans les appels de méthodes. Cependant, cela ne fonctionnera qu'avec gcc.
Voici un exemple d'extraction des informations via une interface de style macro.
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__)
La macro __METHOD_NAME__
Renverra une chaîne de la forme <class>::<method>()
, en coupant le type de retour, les modificateurs et les arguments à partir de ce que __PRETTY_FUNCTION__
Vous donne.
Pour quelque chose qui extrait uniquement le nom de la classe, il faut prendre soin de piéger les situations où il n'y a pas de classe:
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__)
Pas encore. (Je pense __class__
est proposé quelque part). Vous pouvez également essayer d'extraire une partie de classe de __PRETTY_FUNCTION__
.
Je voudrais suggérer boost :: typeindex , ce que j'ai appris de "Effective Modern C++" de Scott Meyer Voici un exemple de base:
Exemple
#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";
}
Compilé avec "g ++ --std = c ++ 14", ceci produit ce qui suit
Sortie
Si vous souhaitez imprimer un type de modèle, c'est facile.
T = double
Pour l'obtenir à partir d'une instance d'objet, utilisez simplement decltype:
le type de fb est: foo_bar
Je pense en utilisant __PRETTY_FUNCTION__
est suffisant, même s’il inclut un espace de noms, c.-à-d. namespace::classname::functionname
jusqu'à ce que __CLASS__
est disponible.
Si votre compilateur se trouve être g++
Et que vous demandez __CLASS__
Parce que vous voulez obtenir le nom de la méthode en cours, classe comprise, __PRETTY_FUNCTION__
Devrait vous aider (selon info gcc
, Section 5.43 Noms de fonctions sous forme de chaînes).
Si vous parlez de MS C++ (vous devriez indiquer, surtout comme __FUNCTION__
est une extension non standard), il y a __FUNCDNAME__
et __FUNCSIG__
_ symboles que vous pouvez analyser
Ma 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__)
Je travaille pour Visual C++ 12.
Vous pouvez obtenir le nom de la fonction, y compris le nom de la classe. Cela peut traiter des fonctions de type 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) + "()";
}
Si vous avez besoin de quelque chose qui produira réellement le nom de la classe lors de la compilation, vous pouvez utiliser C++ 11 pour cela:
#define __CLASS__ std::remove_reference<decltype(classMacroImpl(this))>::type
template<class T> T& classMacroImpl(const T* t);
Je reconnais que ce n’est pas la même chose que __FUNCTION__
_ mais j'ai trouvé ce post en cherchant une réponse comme celle-ci. :RÉ
Voici une solution basée sur le __FUNCTION__
modèles de macro et 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();
}
Voici un exemple d'utilisation de cette classe pour une classe de consignateur
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);
}
}
La sortie de Example::Run
sera alors
Example: 0
Logger<Example>: 0
Fonctionne aussi avec msvc et 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
Cela fonctionne assez bien si vous êtes prêt à payer le coût d'un pointeur.
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__ ) {};
};