convert a c++ program into a template metaprogram?

T

Thomas Heller

I need to convert C preprocessor definitions into python code. The
definitions are dumped out of gccxml (see http://www.gccxml.org) ,
running over the windows header files (for example).

This creates output like this (some excerpts):

#define DATABITS_8 ((WORD)0x0008)
#define KEY_WRITE ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE))
#define MS_NBF "MNBF"
#define PSN_FIRST (0U-200U)
#define RT_ANIICON MAKEINTRESOURCE(22)
#define STG_E_FILENOTFOUND _HRESULT_TYPEDEF_(0x80030002L)

I thought I be clever, and I wrote a couple of overloaded function to
dump out the definitions in Python syntax:

void dump(char *name, LPSTR value)
{
int a = (int)(void *)value;
if ((a & 0xFFFF0000) == 0)
cout << name << " = " << "LPSTR(" << a << ")" << endl;
else
cout << name << " = " << "r\"\"\"" << value << "\"\"\"" << endl;
}

void dump(char *name, int value)
{ cout << name << " = " << value << endl; }

void dump(char *name, unsigned int value)
{ cout << name << " = " << value << endl; }

#define DUMP(sym) dump(#sym, sym)

Now I can create a small program to dump out the definitions, compile it
and call it:

int main (int argc, char **argv)
{
DUMP(DATABITS_8);
DUMP(KEY_WRITE);
DUMP(MS_NBF);
DUMP(PSN_FIRST);
DUMP(RT_ANIICON);
DUMP(STG_E_FILENOTFOUND);
}

This works pretty well, and creates this output:

DATABITS_8 = 8
KEY_WRITE = 131078
MS_NBF = r"""MNBF"""
PSN_FIRST = 4294967096
RT_ANIICON = LPSTR(22)
STG_E_FILENOTFOUND = -2147287038


What I'm wondering now is: Is it possible to do the same with templates,
so that it isn't needed to compile and run the program? gccxml is the
parsing engine of GCC, which spits out the parsing result in xml format,
apparently after templates have been expanded (don't know if that's the
correct term).

As far as I have learned so far (I'm an experienced C programmer, but
not a c++ one) templates can only be invoked and specialized with types,
but not with the types of values. So, is this impossible?

Cheers,

Thomas
 
D

Dave

Thomas Heller said:
I need to convert C preprocessor definitions into python code. The
definitions are dumped out of gccxml (see http://www.gccxml.org) ,
running over the windows header files (for example).

This creates output like this (some excerpts):

#define DATABITS_8 ((WORD)0x0008)
#define KEY_WRITE ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE |
KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE))
#define MS_NBF "MNBF"
#define PSN_FIRST (0U-200U)
#define RT_ANIICON MAKEINTRESOURCE(22)
#define STG_E_FILENOTFOUND _HRESULT_TYPEDEF_(0x80030002L)

I thought I be clever, and I wrote a couple of overloaded function to
dump out the definitions in Python syntax:

void dump(char *name, LPSTR value)
{
int a = (int)(void *)value;
if ((a & 0xFFFF0000) == 0)
cout << name << " = " << "LPSTR(" << a << ")" << endl;
else
cout << name << " = " << "r\"\"\"" << value << "\"\"\"" << endl;
}

void dump(char *name, int value)
{ cout << name << " = " << value << endl; }

void dump(char *name, unsigned int value)
{ cout << name << " = " << value << endl; }

#define DUMP(sym) dump(#sym, sym)

Now I can create a small program to dump out the definitions, compile it
and call it:

int main (int argc, char **argv)
{
DUMP(DATABITS_8);
DUMP(KEY_WRITE);
DUMP(MS_NBF);
DUMP(PSN_FIRST);
DUMP(RT_ANIICON);
DUMP(STG_E_FILENOTFOUND);
}

This works pretty well, and creates this output:

DATABITS_8 = 8
KEY_WRITE = 131078
MS_NBF = r"""MNBF"""
PSN_FIRST = 4294967096
RT_ANIICON = LPSTR(22)
STG_E_FILENOTFOUND = -2147287038


What I'm wondering now is: Is it possible to do the same with templates,
so that it isn't needed to compile and run the program? gccxml is the
parsing engine of GCC, which spits out the parsing result in xml format,
apparently after templates have been expanded (don't know if that's the
correct term).

As far as I have learned so far (I'm an experienced C programmer, but
not a c++ one) templates can only be invoked and specialized with types,
but not with the types of values. So, is this impossible?

Cheers,

Thomas

I can't speak to your whole message, but I can say something about the last
paragraph. Templates may be instantiated with values as well as with other
templates. Types are not the only kinds of parameters you may declare a
template to take. If I recall properly, the values may be of types such as
integer types, pointers and pointers to members. That list may not be
complete...
 
T

Thomas Heller

Dave said:
I can't speak to your whole message, but I can say something about the last
paragraph. Templates may be instantiated with values as well as with other
templates. Types are not the only kinds of parameters you may declare a
template to take. If I recall properly, the values may be of types such as
integer types, pointers and pointers to members. That list may not be
complete...

Dave, what I know so far is that I can define templates that take types,
and instantiate them with the type:

template <class T> class SomeThing {
};

SomeThing<int> foo;
SomeThing<char *> bar;

and templates that take values of a certain type, and instantiate them
with a value of this type:

template <int N> class Blah {
};

Blah<42> foo;
Blah<3> bar;

but what I need is a template that is instantiated by 'calling' it with
values of different types, something like this:

MyClass<42> anIntClass;
MyClass<3U> anUnsignedClass;
MyClass<"abc"> aStringClass;

because the 'values' are #define'd symbols, of which I don't know the
type (but the compiler does).

Thomas
 
V

Victor Bazarov

Thomas said:
[...] what I need is a template that is instantiated by 'calling' it with
values of different types, something like this:

MyClass<42> anIntClass;
MyClass<3U> anUnsignedClass;
MyClass<"abc"> aStringClass;

because the 'values' are #define'd symbols, of which I don't know the
type (but the compiler does).

No, that's not really possible until 'decltype' operator comes along.
It would be better if to instantiate those objects you used a factory
template:

MyClass<int> anIntClass = InstantiateMyClass(42);
MyClass<unsigned> anUnsignedClass = InstantiateMyClass(3U);
MyClass<char const*> aStringClass = InstantiateMyClass("abc");

In this case 'InstantiateMyClass' will be a function template:

template<typename T> MyClass<T> InstantiateMyClass(T t) {
return MyClass<T>(t);
}

Of course, your generator will have to decide the type of the symbol
based on the value (form). That's not that difficult, is it? Nah...

Of course, if you don't need to declare an object and only care about
an expression, you just use 'InstantiateMyClass' function template and
you're all set.

Victor
 
T

Thomas Heller

Victor Bazarov said:
Thomas said:
[...] what I need is a template that is instantiated by 'calling' it with
values of different types, something like this:
MyClass<42> anIntClass;
MyClass<3U> anUnsignedClass;
MyClass<"abc"> aStringClass;
because the 'values' are #define'd symbols, of which I don't know the
type (but the compiler does).

No, that's not really possible until 'decltype' operator comes along.
It would be better if to instantiate those objects you used a factory
template:

MyClass<int> anIntClass = InstantiateMyClass(42);
MyClass<unsigned> anUnsignedClass = InstantiateMyClass(3U);
MyClass<char const*> aStringClass = InstantiateMyClass("abc");

In this case 'InstantiateMyClass' will be a function template:

template<typename T> MyClass<T> InstantiateMyClass(T t) {
return MyClass<T>(t);
}

Of course, your generator will have to decide the type of the symbol
based on the value (form). That's not that difficult, is it? Nah...

Hm, how? That's the whole problem.
Of course, if you don't need to declare an object and only care about
an expression, you just use 'InstantiateMyClass' function template and
you're all set.

See the original post - the program is never executed, and not even
compiled. It is processed with gccxml, which stops after the parsing
phase (it seems class templates have been expanded then), and the parse
tree is written to an XML file. I want to get everything from the xml.

Thomas
 
D

Dave

Thomas Heller said:
Dave, what I know so far is that I can define templates that take types,
and instantiate them with the type:

template <class T> class SomeThing {
};

SomeThing<int> foo;
SomeThing<char *> bar;

and templates that take values of a certain type, and instantiate them
with a value of this type:

template <int N> class Blah {
};

Blah<42> foo;
Blah<3> bar;

but what I need is a template that is instantiated by 'calling' it with
values of different types, something like this:

MyClass<42> anIntClass;
MyClass<3U> anUnsignedClass;
MyClass<"abc"> aStringClass;

because the 'values' are #define'd symbols, of which I don't know the
type (but the compiler does).

Thomas

This may not be exactly what you want, but it is a possibility. C++ does
not have a "typeof" operator. But, you can still determine a hard-coded
value's type at compile time by passing it to a function template and
letting argument deduction tell you the type. The type is then available
for you to use inside the function template. You can use that type to
instantiate your class tempalte with the type of the value, and the value
can also be a template parameter to your class template. See what I've done
below.

There might be a better way. Hmmm, I wonder if there's a typeof in boost...

#include <iostream>

using namespace std;

#define MYVAL 42

template <typename T, T VAL>
class my_class
{
public:
my_class(): m_val(VAL) {}

void foo()
{
cout << m_val << endl;
}

private:
T m_val;
};

template <typename T>
void func(T)
{
my_class<T, MYVAL> var; // Here, we really use the value.

var.foo();
}

int main()
{
func(MYVAL); // Passing MYVAL here just conveys type information,
// we're not actually using it to pass the value.

return 0;
}
 
V

Victor Bazarov

Thomas Heller said:
[...]
See the original post - the program is never executed, and not even
compiled. It is processed with gccxml, which stops after the parsing
phase (it seems class templates have been expanded then), and the parse
tree is written to an XML file. I want to get everything from the xml.

You _could_ supply the type in the same XML document, right next to the
literal, no?
 
T

Thomas Heller

Dave said:
This may not be exactly what you want, but it is a possibility. C++ does
not have a "typeof" operator. But, you can still determine a hard-coded
value's type at compile time by passing it to a function template and
letting argument deduction tell you the type. The type is then available
for you to use inside the function template. You can use that type to
instantiate your class tempalte with the type of the value, and the value
can also be a template parameter to your class template. See what I've done
below.

There might be a better way. Hmmm, I wonder if there's a typeof in boost...
[...]

The problem with the approach you describe above is that string literals
cannot be used to call a class template (I'm not sure about the
terminology here). I get errors like this:

a.cpp:27: error: string literal "blahblah" is not a valid template
argument because it is the address of an object with static linkage

But, I found a somewhat simpler solution. The value can also be made
available as default argument for a function template. So, this is the
final test program I have, and all I need can be found in the xml that
gccxml generates:

#define MYVAL 999999
#define MYUVAL (0U - 1U)
#define MYSTRING "blahblah"
#define MYCHAR 'c'

template <typename T> T symbol_MYSTRING(T, T val = MYSTRING) {}
template <typename T> T symbol_MYCHAR(T, T val = MYCHAR) {}
template <typename T> T symbol_MYUVAL(T, T val = MYUVAL) {}
template <typename T> T symbol_MYVAL(T, T val = MYVAL) {}

int main()
{
symbol_MYSTRING(MYSTRING, MYSTRING);
symbol_MYCHAR(MYCHAR, MYCHAR);
symbol_MYVAL(MYVAL, MYVAL);
symbol_MYUVAL(MYUVAL, MYUVAL);
}

Many, many thanks for your help,

Thomas
 

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

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top