Compile typedef-ed substrings

M

mrstephengross

Hi folks! I'm trying to do something that I'm pretty sure you can't do
in C++. But what the heck! Maybe it can work...

I want to figure out how to use macros and templates to turn the
following code snippet:

void SomeClass::someFunction() { /* ... */ }

Into:

void SomeClass::someFunction() { typeid(SomeClass); }

So far, I haven't figured much out. Consider the following macro:

#define FOO(f) f typeid(#f);

It will turn:

void FOO(SomeClass::someFunction() {) /* ... */ }

into:

void SomeClass::someFunction() { typeid(SomeClass::someFunction {); }

Which of course won't compile. The preprocessor is very limited, and
can't parse apart macro arguments. I'm wondering if there's some way to
do it with templates. For instance:

#define FOO(f) f typeid(mymagictemplate<#f>::type);

Any ideas? So far I've come up short.

Thanks,
--Steve ([email protected])
 
V

Victor Bazarov

mrstephengross said:
Hi folks! I'm trying to do something that I'm pretty sure you can't do
in C++. But what the heck! Maybe it can work...

I want to figure out how to use macros and templates to turn the
following code snippet:

void SomeClass::someFunction() { /* ... */ }

Into:

void SomeClass::someFunction() { typeid(SomeClass); }

Huh? Perhaps you should simply use the search-and-replace feature of
your text editor?
So far, I haven't figured much out. Consider the following macro:

#define FOO(f) f typeid(#f);

It will turn:

void FOO(SomeClass::someFunction() {) /* ... */ }

into:

void SomeClass::someFunction() { typeid(SomeClass::someFunction {); }

No joke... :-/
Which of course won't compile. The preprocessor is very limited, and
can't parse apart macro arguments. I'm wondering if there's some way to
do it with templates. For instance:

#define FOO(f) f typeid(mymagictemplate<#f>::type);

Something similar to

template<void (T::*f)()> struct mymagictemplate {
typedef T type;
};

but do lose the #.
Any ideas? So far I've come up short.

Can you maybe specify the problem you're trying to solve instead of giving
a non-working "solution" and make use *guess* the problem?

V
 
M

mrstephengross

Can you maybe specify the problem you're trying to solve instead of
giving
a non-working "solution" and make use *guess* the problem?

Sure... We want to automagically extract the class name from any given
function definition and *use* it in the code. So for any given
function:

SomeClass::foo() { /* ... */ }

We want to automagically turn it into:

SomeClass::foo() { typeid(SomeClass); }

Or even:

SomeClass::foo() { std::cout << typeid(SomeClass).name(); }
(For debugging purposes)

We need to find a way to do it automatically so that we can apply it
across-the-board to the whole program and produce complete debugging
information.

Ideas?

--Steve
 
V

Victor Bazarov

mrstephengross said:
Sure... We want to automagically extract the class name from any given
function definition and *use* it in the code. So for any given
function:

SomeClass::foo() { /* ... */ }

We want to automagically turn it into:

SomeClass::foo() { typeid(SomeClass); }

Or even:

SomeClass::foo() { std::cout << typeid(SomeClass).name(); }
(For debugging purposes)

We need to find a way to do it automatically so that we can apply it
across-the-board to the whole program and produce complete debugging
information.

Ideas?

How about 'typeid(*this)' ? There are other things that can help
extracting class out of references (if you're so inclined)...

template<class T> struct deref { typedef T type; };
template<class T> struct deref<T&> { typedef T type; };
template<class T> struct deref<T const&> { typedef T type; };
...

(this is for illustration only, I've seen it somewhere, you should try
it before you buy)

Later on, you will actually have 'decltype', it's in the works.

Keep in mind that 'type_info::name' doesn't have to return anything of
any value to the debugger. It's not specified to be extremely useful,
just barely, and depends very much on the implementation.

V
 
M

mrstephengross

The problem with 'typeid(*this)' is that the function may be static, in
which case 'this' is not available...

--Steve
 
V

Victor Bazarov

mrstephengross said:
The problem with 'typeid(*this)' is that the function may be static, in
which case 'this' is not available...

I am honestly not sure what you hope to get out of it. If you have to
edit your code *anyway*, why don't you just use the class name instead of
some obscure macro or a template?

V
 
M

mrstephengross

The problem with 'typeid(*this)' is that the function may be
static, in
I am honestly not sure what you hope to get out of it. If you have to
edit your code *anyway*, why don't you just use the class name instead of
some obscure macro or a template?

Let's say you've got the following code:

==========================================
class foo { void func1(); void func2(); void func3(); ... void funcX();
};

void foo::func1() { ... }
void foo::func2() { ... }
void foo::func3() { ... }
....
void foo::funcX() { ... }
==========================================

I'm trying to find a *quick* way to get the class name printed when
each function executes. If I do it with a macro, then I want that macro
to be very short and easy to insert, given the large number of
functions I'm dealing with:

==========================================
class foo { void func1(); void func2(); void func3(); ... void funcX();
};

#define MACRO(f) f std::cout << typeid(magictemplate<#f>::type);

void MACRO(foo::func1() {) ... }
void MACRO(foo::func2() {) ... }
void MACRO(foo::func3() {) ... }
....
void MACRO(foo::funcX() {) ... }
==========================================

Obviously, I could make the macro take class name as an argument, but
the code will get wordier and less readable:


==========================================
class foo { void func1(); void func2(); void func3(); ... void funcX();
};

#define MACRO(classname, f) f std::cout << typeid(classname);

void MACRO(foo, foo::func1() {) ... }
void MACRO(foo, foo::func2() {) ... }
void MACRO(foo, foo::func3() {) ... }
....
void MACRO(foo, foo::funcX() {) ... }
==========================================

Since I want the macro to be as non-intrusive as possible, I want to
see if there's a way to extract the classname portion of the function
definition at compile time. (I can do it at runtime, but I'll run into
namespace issues: NAMESPACE1::fooclass might be reported as 'fooclass'
instead of 'NAMESPACE1::fooclass').

--Steve
 
A

acehreli

mrstephengross said:
I'm trying to find a *quick* way to get the class name printed when
each function executes. [...]
I want to
see if there's a way to extract the classname portion of the function
definition at compile time. (I can do it at runtime, but I'll run into
namespace issues: NAMESPACE1::fooclass might be reported as 'fooclass'
instead of 'NAMESPACE1::fooclass').

The following method seems to be easier than what you have in mind, and
works with namespaces. It uses g++'s __PRETTY_FUNCTION__ variable. You
should be able to find similar features if your compiler is different.

Ali

#include <iostream>
#include <ostream>
#include <string>
#include <assert.h>

#define FUNCTION_INFO \
do \
{ \
std::cout \
<< "::" \
<< pluckClassName(__PRETTY_FUNCTION__) \
<< '\n'; \
} \
while (0);

std::string pluckClassName(std::string const & prettyName)
{
using std::string;

string::size_type beg = prettyName.find(" ");

// We expect a space after the return type
assert(beg != string::npos);

++beg; // Jump over the space
string::size_type end = prettyName.rfind("::");

return ((end == string::npos)
? ""
: prettyName.substr(beg, end - beg));
}

namespace Namespace
{

class Class
{
public:

void foo() { FUNCTION_INFO; }
};

} // Namespace

class FreeClass
{
public:

void bar() { FUNCTION_INFO; }
};

int freeFunction()
{
FUNCTION_INFO;
return 0;
}

int main()
{
Namespace::Class nc;
nc.foo();

FreeClass fc;
fc.bar();

freeFunction();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top