Related
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
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
For C++ types, the <type_traits> header gives us many useful compile-time reflection capabilities. E.g. std::is_base_of<B, D>::value determines at compile-time whether B is a base class of D.
I wonder if it would be possible to detect namespace membership along similar lines? E.g. given a namespace N with a type T, is there a way to determine whether T is contained within N using a macro expression of the form IS_NAMESPACE_MEMBER_OF(T,N).
I'd prefer a compile-time answer through any sort of SFINAE / ADL type of trick. Or, if it isn't possible, some sort of reasoning why the Standard would not allow this.
A non-portable and run-time hack would be to regex typeid(T).name() for N, but this is rather tedious and not at compile-time.
EDIT1: as pointed out by K-ballo, a namespace cannot be used as a template parameter so a type-trait seems impossible.
EDIT2: here's the skeleton as hinted to by K-ballo: what nifty test can (or cannot?) be cooked up there?
#define IS_NAMESPACE_MEMBER_OF(T, N) \
\
// global declaration \
void test(T); \
\
// namespace declaration \
namespace N { \
void test(T); \
} \
\
// some clever name lookup / sizeof / SFINAE test!
A namespace is not a valid template parameter, so it could never be a class trait. Perhaps you can do something obscure with macros though. You could maybe inject functions in the test namespace and use ADL together with a sizeof/decltype trick to see which overload gets picked.
You can test whether the namespace is accessible (looked up by the compiler), via ADL, from the type.
Suppose that we want to check if type A comes from namespace foo, we can try to use a type that appears only in foo (e.g. a generic function foo::foo_inner_func(T&&)) via the use of A to see if we reach the namespace. If we do it in a SFINAE context then this can result with the answer we are looking for: whether namespace foo is accessible via A.
In many cases that would be the answer of whether the type belongs to this namespace, but in some cases it may identify a namespace as accessible by ADL even though the type doesn't come from this namespace. For example if A is from namespace foo and B which derives from A is from another namespace, B still "sees" foo via ADL. Also std::vector<A> "sees" foo via ADL (and also "sees" std via ADL).
The idea of using ADL was already presented here: Check if a type is from a particular namespace.
Here is the macro version that allows querying any type (almost) for any namespace (almost):
#define create_ns_checker(ns) \
namespace ns { \
template <typename T> \
constexpr std::true_type ns##FindmeNsADLHelper(T&&); \
} \
namespace ns##_type_traits { \
class ns##SecondBestMatchType {}; \
class ns##BestExactMatchType : public ns##SecondBestMatchType {}; \
namespace helpers { \
template <typename T> \
auto TestNs(ns##_type_traits::ns##BestExactMatchType) \
-> decltype(ns##FindmeNsADLHelper(std::declval<T>())); \
template <typename T> \
auto TestNs(ns##_type_traits::ns##SecondBestMatchType) \
-> std::false_type; \
} \
template <typename T> \
constexpr bool ns##IsFindmeNs() { \
return decltype(helpers::TestNs<std::decay_t<T>> \
(ns##BestExactMatchType{}))::value; \
} \
}
#define is_in_ns(Type, ns) \
(ns##_type_traits::ns##IsFindmeNs<Type>())
A small printing utility:
#define print_is_in_ns(Type, ns) \
[]() { \
std::cout << #Type << " in " << #ns << ": " \
<< is_in_ns(Type, ns) << std::endl; \
}()
Creating the checkers with the macro:
create_ns_checker(findme)
create_ns_checker(other)
create_ns_checker(std)
Checking it for the following types:
namespace other {
struct B {};
}
struct C {};
namespace findme {
struct A {};
namespace inner {
struct A {};
}
create_ns_checker(inner)
}
Testing in findme context:
namespace findme {
void test() {
using namespace other;
// add the below in and the results change, as it should!
// using inner::A;
using std::string;
std::cout << std::boolalpha;
print_is_in_ns(int, std); // false
print_is_in_ns(string, std); // true
print_is_in_ns(A, findme); // true
print_is_in_ns(A, inner); // false
print_is_in_ns(inner::A, findme); // false
print_is_in_ns(inner::A, inner); // true
print_is_in_ns(B, findme); // false
print_is_in_ns(B, other); // true
print_is_in_ns(C, findme); // false
}
}
Testing in main:
int main() {
using std::string;
using findme::A;
std::cout << std::boolalpha;
print_is_in_ns(int, std); // false
print_is_in_ns(string, std); // true
print_is_in_ns(string, findme); // false
print_is_in_ns(findme::A, findme); // true
print_is_in_ns(findme::inner::A, findme); // false
print_is_in_ns(other::B, findme); // false
print_is_in_ns(other::B, other); // true
print_is_in_ns(C, findme); // false
print_is_in_ns(std::vector<A>, findme); // falsely says true :-(
print_is_in_ns(std::vector<A>, std); // true
std::cout << "-----------------" << std::endl;
findme::test();
}
Code: https://godbolt.org/z/8Ed89v
I want to define a macro that can be invoked in different places (at file scope) in order to create functions that do something. (In the example below the functions just print a message, but of course my real intent is to do some other useful stuff.) The challenge is that I want some "manager" function (in my example it will just be main()) to somehow succeed in getting them all invoked (in any order) without any of the code being dependent on the macro invocations (except for the macro invocations themselves, of course). What I mean is that once the file is written, another programmer would be able to just insert a few new macro invocations at various places or delete some of the existing invocations, and the code would still work without any further change. I realize this can be done using static objects but I want to explore a different approach. I'm going to use some template trickery and the fact that __LINE__ is monotone increasing.
#include <iostream>
using namespace std;
template<int i>
inline void f()
{
f<i-1>();
}
#define START_REGISTRATION \
template<> \
inline void f<__LINE__>() {} /* stop the recursion */ \
template<> void f<__LINE__>() /* force semicolon */
#define REGISTER(msg) \
template<> \
inline void f<__LINE__>() \
{ \
cout << #msg << endl; \
f<__LINE__ - 1>(); \
} \
template<> void f<__LINE__>() /* force semicolon */
// Unrelated code ...
START_REGISTRATION;
// Unrelated code ...
REGISTER(message 1);
// Unrelated code ...
REGISTER(message 2);
// Unrelated code ...
REGISTER(message 3);
// Unrelated code ...
// manager function (in this case main() )
int main()
{
f<__LINE__>();
}
This prints
message 3
message 2
message 1
as expected.
This solution has a few drawbacks.
Can't invoke REGISTER twice on the same line.
Will break if #line is played with.
Need to put the manager after all invocations of REGISTER.
Increased compile time due to the recursive instantiations.
Unless the "dummy" instantiations of f are all inlined away, the call-stack depth at runtime will be as great as the number of lines between START_REGISTRATION; and f<__LINE__>(); in the manager.
Code bloat: unless the "dummy" instantiations of f are all inlined away, the number of instantiations will similarly be be as great.
The excessive instantiation recursion depth is likely to hit the compiler's limit (500 by default on my system).
Issues 1-4 I don't really mind. Issue 5 can be eliminated by having each function return a pointer to the previous one, and having the manager use these pointers to call the functions iteratively rather than having them call each other. Issue 6 can be eliminated by creating a similar class template construct that is able to compute for each invocation of REGISTER what function was instantiated in the previous invocation and thus only instantiate the functions that actually do something. The excessive instantiation will then be shifted from the function template to the class template, but the class instantiations would only tax the compiler; they wouldn't trigger any code generation. So my real concern is Issue 7, and the question is: is there a way to restructure things so that the compiler does the instantiations iteratively rather than recursively. I am also open to different approaches altogether (apart from those involving static objects). One simple solution is to group all registrations together right before the manager (or add a STOP_REGISTRATION macro to end the block of registrations) but that would defeat a significant part of my purpose (registering stuff next to the code that defines it).
Edit: There have been some interesting suggestions, but I'm afraid I wasn't making myself clear in terms of what I hope to achieve. I'm really interested in two things: solving the problem as posed (i.e., no statics, single line per registration, no additional changes when adding/removing registrations, and, although I neglected to say so, only standard C++ --- hence, no boost). As I said in the comments below, my interest is more theoretical in nature: I'm hoping to learn some new techniques. Hence, I would really like to focus on restructuring things so the recursion is eliminated (or at least reduced) or finding a different approach that satisfies the constraints I laid out above.
Edit 2: MSalter's solution is a large step forward. At first I thought that every registration would incur the full cost of lines up to it, but then I realized that of course a function can be instantiated only once, so in terms of instantiations we pay the same price as in linear search, but the recursion depth becomes logarithmic. If I get around to it, I'll post a full solution eliminating Issues 5-7. It would still be nice, though, to see if it can be done in constant recursion depth, and best, with the number of instantiations linear in the number of invocations (a-la the boost solution).
Edit 3: Here's the full solution.
#define START_REGISTRATION \
template<int lo, int hi> \
struct LastReg { \
enum { \
LINE_NUM = LastReg<(lo + hi)/2 + 1, hi>::LINE_NUM ? \
static_cast<int>(LastReg<(lo + hi)/2 + 1, hi>::LINE_NUM) : \
static_cast<int>(LastReg<lo, (lo + hi)/2>::LINE_NUM) \
}; \
}; \
template<int l> \
struct LastReg<l, l> { \
enum { LINE_NUM = 0 }; \
}; \
template<int l> \
struct PrevReg { \
enum { LINE_NUM = LastReg<__LINE__ + 1, l - 1>::LINE_NUM }; \
}; \
template<int l> void Register() {} \
template<int l> void Register() /* force semicolon */
#define REGISTER(msg) \
template<> \
struct LastReg<__LINE__, __LINE__> { \
enum { LINE_NUM = __LINE__ }; \
}; \
template<> \
void Register<__LINE__>() \
{ \
cout << __LINE__ << ":" << #msg << endl; \
Register<PrevReg<__LINE__>::LINE_NUM>(); \
} \
template<> void Register<__LINE__>() /* force semicolon */
#define END_REGISTRATION \
void RegisterAll() \
{ \
Register<PrevReg<__LINE__>::LINE_NUM>(); \
} \
void RegisterAll() /* force semicolon */
START_REGISTRATION;
REGISTER(message 1);
REGISTER(message 2);
END_REGISTRATION;
int main()
{
RegisterAll();
}
The problem you face is that you're doing a linear search for f<i>, which causes an excessive number of instantiations.
The solution is to let f<i> call g<i,0>. This in turn calls g<i,i/2> and g<i/2,0>, which call g<i,i/2+i/4>, g<i/2+i/4,i/2>, g<i/2,i/4> and g<i/4, 0> ectetera. You'll of course specialize g<__LINE__, __LINE__> inside REGISTER().
Instantiating f<65536> will still cause 65536 template instantiations (you're effectively checking all previous 65536 lines), but the recursion depth is limited to log(65536), or 16 levels. That's doable.
Perhaps something like:
template<typename T>
struct register_struct {
virtual void operator()() = 0;
register_struct();
register_struct *pNext;
};
template<typename T>
struct registry {
static register_struct<T> *chain;
static void walk() {
register_struct<T> *p = chain;
while (p) {
(*p)();
p = p->pNext;
}
}
};
template<typename T>
register_struct<T> *registry<T>::chain = NULL;
template<typename T>
register_struct<T>::register_struct()
{
pNext = registry<T>::chain;
registry<T>::chain = this;
}
#define DECL_REGISTRY(name) \
struct tag_##name { } ; \
void name() { registry<tag_##name>::walk(); }
#define JOIN_EXPAND(x, y) JOIN_EXPAND_2(x, y)
#define JOIN_EXPAND_2(x, y) x ## y
// Invoke REGISTER_PRINT at file scope!
#define REGISTER_PRINT(name, text) \
namespace { \
static struct : public register_struct<tag_##name> { \
void operator()() { \
std::cout << text << std::endl; \
} \
} JOIN_EXPAND(rs_##name##_, __LINE__); \
}
DECL_REGISTRY(foo);
REGISTER_PRINT(foo, "hello")
REGISTER_PRINT(foo, "world")
int main() {
foo();
return 0;
}
This will fix the recursive instantiation issues, but you're still limited to one registration per line. However, since the registrations are at file scope, this should (hopefully!) be less of a problem.
Note that this is unsafe to use if you expect to invoke these prior to main() - you must allow static constructors to complete before using it.
I've once done something similar, which instantiates only a limited count of specializations. The goal was to aggregate all the specializations into an array of pointers and access them with a single method via the enum, but you easily can adapt it to your similar (as I suppose) needs.
#include <iostream>
using namespace std;
class I {
public:
virtual ~I() {};
virtual void P(int index) = 0;
enum Item {
Item0,
Item1,
Item2,
Item3,
Item4,
ItemNum
};
};
template <class T> class A: public I {
public:
A() {
Unroll<A<T>, ItemNum> tmp (m_F);
}
virtual ~A() {
}
void P(int index) { (this->*m_F[index])(); }
protected:
typedef void (A<T>::*F)();
F m_F[ItemNum];
template <int N> void p() { cout << "default!" << endl; }
template <class W, int C> struct Unroll
{
Unroll(typename W::F * dest)
{
dest[C-1] = & W::template p<C-1>;
Unroll<W, C-1> u(dest);
}
};
};
template <class T> template <class W> struct A<T>::Unroll<W, 0>
{ public: Unroll(typename W::F * dest) {} };
class B: public A<B>
{
public:
};
template <> template <> void A<B>::p<A<B>::Item1>() { cout << 1 << endl; }
template <> template <> void A<B>::p<A<B>::Item2>() { cout << 2 << endl; }
template <> template <> void A<B>::p<A<B>::Item4>() { cout << "it hacking works!" << endl; }
int main()
{
I *a = new B;
for (int i = 0; i < I::ItemNum; ++i) a->P(i);
return 0;
}
Here is a solution that limits recursion to the number of functions actually registered. Instead of using __LINE__ as the id, I used BOOST_PP_COUNTER, which is an incrementing counter available to the preprocessor.
The trick is that you can't increment the counter inside a macro since the increment is done through the inclusion of a header file. Consequently, I had to rely on file inclusion too, hence needing two lines instead of one to register a message (one line to define the message, and one line to actually register it).
Here is the code:
//register.hpp
#include <boost/preprocessor/slot/counter.hpp>
// general template function, not defined
template <unsigned int ID>
void f();
// base case, to stop recursion
template <>
void f<0>() {}
// macro to "hide" the name of the header to include (which should be in a
// "hidden" folder like "detail" in Boost
#define REGISTER() "actually_register_msg.hpp"
//actually_register_msg.hpp
#include <boost/preprocessor/stringize.hpp>
// increment the counter
#include BOOST_PP_UPDATE_COUNTER()
template<>
inline void f< BOOST_PP_COUNTER >()
{
std::cout << BOOST_PP_STRINGIZE( MSG_TO_REGISTER ) << std::endl;
f< BOOST_PP_COUNTER - 1 >(); // call previously registered function
}
// to avoid warning and registering multiple times the same message
#undef MSG_TO_REGISTER
// id of the last registered function
#define LAST_FUNCTION_ID BOOST_PP_COUNTER
// main.cpp
#define MSG_TO_REGISTER message 1
#include REGISTER()
#define MSG_TO_REGISTER message 2
#include REGISTER()
#define MSG_TO_REGISTER message 3
#include REGISTER()
int main()
{
f< LAST_FUNCTION_ID >();
}
Like your code, this prints
message 3
message 2
message 1
Of course, the registering call is a bit less pretty (one #define and one #include instead of a single macro call), but you avoid a lot of unecessary template instantiations.
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