How do i find the struct name from the instance? [duplicate] - c++

Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?

You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.

use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}

To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}

Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.

Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}

You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...

You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}

An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*

Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts

Related

How to pretty print the name of a template parameter at compile time

The question is rather simple: how to pretty print the name of a template parameter in a C++ class and assign it to a class variable at compile time ?
It seems that both typeinfo (typeid) and boost::typeindex must be evaluated at runtime or as least some part of them. This apparently does not allow the compiler to completely solve a constexpr containing a call to one of this function.
template<typename T>
class X
{
public:
static const char * name = /* SOME C++ code transforming T in a string (either std::string or char */
};
What am I missing ?
Is it only possible to generate a name at runtime ? In that case, does I really need an instantiated object ? It doesn't seem right to me, because the following perfectly work without any instance:
#include <iostream>
#include <string>
#include <boost/type_index.hpp>
using namespace std;
template<class T>
class X
{
public:
static std::string name()
{
return boost::typeindex::type_id<T>().pretty_name();
}
};
struct foobar {};
int main()
{
cout << X<int>::name() << endl;
cout << X<foobar>::name()<< endl;
}
So instead of having name() as a class method, I'd like to have it as a class variable.
I think, it is possible to use custom Type Traits. Please see the next example:
#include <iostream>
#include <string>
using namespace std;
//Using stub type traits
template <class T>
struct TypeTraits;
//your TypeTraits for specific types...
template<>
struct TypeTraits<int>
{
constexpr static const char *name = "int";
};
template<class T>
class X
{
public:
constexpr static const char * name = TypeTraits<T>::name;
};
struct foobar {};
//TypeTraits for custom foobar
template<>
struct TypeTraits<foobar>
{
constexpr static const char *name = "foobar";
};
int main()
{
//Now you can use static member here
cout << X<int>::name << endl;
cout << X<foobar>::name<< endl;
}
Also TypeTraits can be used (and expanded) for other purposes.

C++ How do you output an object's type [duplicate]

Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?
You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.
use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}
To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.
Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...
You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}
An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*
Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts

How can I get the class name from a C++ object?

Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?
You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.
use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}
To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.
Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...
You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}
An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*
Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts

Noob boost::bind member function callback question

#include <boost/bind.hpp>
#include <iostream>
using namespace std;
using boost::bind;
class A {
public:
void print(string &s) {
cout << s.c_str() << endl;
}
};
typedef void (*callback)();
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void main() {
A a;
B b;
string s("message");
b.set_callback(bind(A::print, &a, s));
b.do_callback();
}
So what I'm trying to do is to have the print method of A stream "message" to cout when b's callback is activated. I'm getting an unexpected number of arguments error from msvc10. I'm sure this is super noob basic and I'm sorry in advance.
replace typedef void (*callback)(); with typedef boost::function<void()> callback;
A bound function doesn't produce an ordinary function, so you cannot just store it in a regular function pointer. However, boost::function is able to handle anything as long as it is callable with the correct signature, so that's what you want. It will work with a function pointer, or a functor created with bind.
After a few corrections to your code, I came up with this:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
// i prefer explicit namespaces, but that's a matter of preference
class A {
public:
// prefer const refs to regular refs unless you need to modify the argument!
void print(const std::string &s) {
// no need for .c_str() here, cout knows how to output a std::string just fine :-)
std::cout << s << std::endl;
}
};
// holds any arity 0 callable "thing" which returns void
typedef boost::function<void()> callback;
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void regular_function() {
std::cout << "regular!" << std::endl;
}
// the return type for main is int, never anything else
// however, in c++, you may omit the "return 0;" from main (and only main)
// which will have the same effect as if you had a "return 0;" as the last line
// of main
int main() {
A a;
B b;
std::string s("message");
// you forget the "&" here before A::print!
b.set_callback(boost::bind(&A::print, &a, s));
b.do_callback();
// this will work for regular function pointers too, yay!
b.set_callback(regular_function);
b.do_callback();
}

Can a C++ Class Constructor Know Its Instance Name?

Is it possible to know the object instance name / variable name from within a class method? For example:
#include <iostream>
using namespace std;
class Foo {
public:
void Print();
};
void Foo::Print() {
// what should be ????????? below ?
// cout << "Instance name = " << ?????????;
}
int main() {
Foo a, b;
a.Print();
b.Print();
return 0;
}
No. Variable names are for the programmer, the compiler sees addresses.
Other languages that provide meta-data/reflection about their program might provide this functionality, C++ isn't one of those languages.
Not with the language itself, but you could code something like:
#include <iostream>
#include <string>
class Foo
{
public:
Foo(const std::string& name) { m_name = name;}
void Print() { std::cout << "Instance name = " << m_name << std::endl; }
private:
std::string m_name;
};
int main()
{
Foo a("a");
Foo b("b");
a.Print();
b.Print();
return 0;
}
Variable names do not exist in the compiled code.
However you can use some #define to get the name in preprocessing and let the names be populated before the compile.
Something like this:
#define SHOW(a) std::cout << #a << ": " << (a) << std::endl
// ...
int i = 2;
SHOW (i);
What would that mean?
void f(T const& p) {
cout << p.name();
}
T r() {
T c;
return c;
}
void g() {
T a;
cout << a.name();
T & b = a;
cout << b.name();
T * ptr = &b;
cout << ptr->name();
T d = r();
cout << d.name();
}
What would you expect? "a" each time? And what about c/d?
Variable names don't survive compilation. The best you can do is to pass the variable name into the object constructor and store it inside the object by using a macro. The latter will lead to really ugly code so you would only want this as a last resort.
For the bounty:
This is one of the biggest and most disgusting hacks I've ever created but its good enough for debug reasons in my opinion
#include <iostream>
#include <typeinfo>
#define DEBUG_INSTANCE( classtype, name ) class _ ## classtype ## _INSTANCE_ ## name ## _ : public classtype \
{ \
public: \
_ ## classtype ## _INSTANCE_ ## name ## _ (){ } \
}; \
_ ## classtype ## _INSTANCE_ ## name ## _ name
class Foo {
public:
virtual void _MakeTypeIDRunTime() { }
// A virtual method in the class forces typeid(*this) to be used runtime rather than compiled
// See: https://stackoverflow.com/a/6747130/1924602
void Print();
};
void Foo::Print() {
std::cout << "Instance name = " << typeid(*this).name() << std::endl;
}
int main()
{
DEBUG_INSTANCE(Foo, a);
DEBUG_INSTANCE(Foo, b);
a.Print();
b.Print();
system("PAUSE");
return 0;
}
Output:
Instance name = ?AV_Foo_INSTANCE_a_#?1?main#
Instance name = ?AV_Foo_INSTANCE_b_#?1?main#
Press any key to continue . . .
This macro will create a class that inherits Foo and name contains the instance name. Only limitation is that Foo has a default constructor and must contain a virtual method in order for typeid to accept inherited classes and be called used at runtime. See https://stackoverflow.com/a/6747130/1924602 for a better explanation
Might be possible to support constructors if you use the __VA_ARGS__ macro
It is certainly possible for an instance to know its name from within the class method:
#include <iostream>
class Foo {
public:
void Print() { std::cout << "Instance name = " << this << std::endl; }
};
int main() {
Foo a, b;
a.Print();
b.Print();
return 0;
}
will produce the output similar to this:
Instance name = 0x7fff502b8b48
Instance name = 0x7fff502b8b40
As for knowing the variable name, it is certainly not possible. The existence of the object does not imply the existence of the variable - this instance:
new Foo();
will exist for the remaining duration of the process, yet will never be associated with any variable. The language concept of variables is not reflected in the contents of said variables, and any potential relation between language variable and an object is expressed only in the generated code and not in generated data or meta-data. Barring of course the access to the debug information which, as already pointed out, is not part of the language.
It is not possible with the language itself. However, you can use preprocessor to get it. But it is not going to be clear and you will have to be careful if your classes have different constructors. Also you will have to do it in each class.
I reuse the example of Steven Keith in combination with #define preprocessor:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const string& name) : m_name(name) {}
void Print() { cout << "Instance name = " << m_name << endl; }
private:
string m_name;
};
#define DRESSED_Foo(var) Foo var(#var)
int main()
{
DRESSED_Foo(a);
DRESSED_Foo(b);
a.Print();
b.Print();
return 0;
}
The keyword this
I'm new to programming, but having studied class structure I believe what you might be looking for is the keyword this. As in the example below (taken from cplusplus.com), you can see that this is used anywhere the class needs to refer to itself.
Therefore, it is possible for a constructor to do this as well.
// example on this
#include <iostream>
using namespace std;
class Dummy {
public:
bool isitme (Dummy& param);
};
bool Dummy::isitme (Dummy& param)
{
if (&param == this) return true;
else return false;
}
int main () {
Dummy a;
Dummy* b = &a;
if ( b->isitme(a) )
cout << "yes, &a is b\n";
return 0;
}
http://www.cplusplus.com/doc/tutorial/templates/
It is not possible. C++ does not have a concept of "reflection" like .NET platform.
But MFC library has CRunTime class - you can see for example.
Debug symbols do not exist as far as C++ is concerned. As a result, no C++ mechanism allows you to do anything with them.
Would it be possible to create platform-specific solution which would work? Possible. One would have to analyze the image of the process in memory, parse it according to specific format, figure out debug symbols (and frames) and map them to addresses. Essentially, debug itself.
Does it worth the trouble? Not in my opinion.
You can do it using #define. Define a macro which would save variable name inside class:
#include <iostream>
#include <string>
using namespace std;
#define CREATE_FOO(f) Foo f = Foo(#f);
class Foo {
public:
void Print() const;
Foo(string s): name(s) {};
protected:
string name;
};
void Foo::Print() const {
cout << "Instance name = " << name;
}
int main() {
CREATE_FOO(a);
CREATE_FOO(b);
a.Print();
b.Print();
return 0;
}
This is not possible "Directly", consider this simple program;
// stove.cpp
#include <string.h>
#include <stdio.h>
#include <iostream>
using namespace std;
class Foo {
char* t;
size_t length;
public:
Foo()
{
t = new char(8);
t = static_cast<char*>(static_cast<void*>(this));
}
void Print();
};
void Foo::Print() {
// what should be ????????? below ?
cout << this << " " << strlen (t) << t << endl;
}
int main() {
Foo a;
a.Print();
Foo b;
b.Print();
return 0;
}
you can check the value of t in gdb for both a and b objects,
1) run binary in gdb and put breakpoints on lines where both objects a and b gets created.
2) for both objects a and b , after creation (or in print function, check
print this
print t
18 }
(gdb) print this
$1 = (Foo * const) 0x7fffffffe6e0
(gdb) print t
$2 = 0x7fffffffe6e0 "\340\346\377\377\377\177"
...
...
...
30 Foo b;
(gdb) s
Foo::Foo (this=0x7fffffffe6d0) at stov.cpp:15
15 t = new char(8);
(gdb) n
16 t = static_cast<char*>(static_cast<void*>(this));
(gdb) n
18 }
(gdb) print this
$3 = (Foo * const) 0x7fffffffe6d0
(gdb) print t
$4 = 0x7fffffffe6d0 "\320\346\377\377\377\177"
class Food {
private:
uint8_t m_Temperature; // cooking temperature
public:
//constructor
Food (uint16_t Temperature) {
m_Temperature = Temperature;
}
//forward declaration
void CookIt(uint16_t NewTemperature);
}; // class
Food Burger(123);
Food Fries(233);
void Food::CookIt(uint16_t NewTemperature) {
Serial.print("I am cooking ");
if(this==&Burger) Serial.print("burger");
if(this==&Fries) Serial.print("fries");
Serial.print(" at ");
Serial.print(NewTemperature);
Serial.println(" Deg C");
Serial.println();
}