Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2004-08-14 12:57:36


> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Christoph Ludwig

> Just for clarification: You say that in the following
>
> template<class> struct pack;
>
> template<class T> struct<void (T)> {
> typedef T type;
> };
>
> MY_MACRO(pack<void (void)>::type)
> MY_MACRO(pack<void (MyTemplate<int, int>[10])>::type)
>
> both macro expansions won't work (or more precisely, result
> in code that will fail or yield unwanted results when
> compiled)? Hm, I probably should peruse my copy of the book
> by Vandvoorde and Josuttis again, but this makes kind of sense.

Yes, 'void (void)' is a valid function type, but it is the same as 'void ()'
which won't match the partial specialization (though that could be made to work,
but it isn't worth it). The following two function types are identical because
array types decay to pointers when used as parameter types.

void (MyTemplate<int, int>[10])
void (MyTemplate<int, int>*)

Similar thing for:

void (int (int))
void (int (*)(int))

because function types used as parameter types transform to pointers to function
types.

I suppose another way to do it would be:

template<class T> struct id {
    typedef T type;
};

template<class> struct pack;
template<class T> struct pack<void (id<T>)> : id<T> { };

MY_MACRO(pack<void (id<void>)>::type)
MY_MACRO(pack<void (id<MyTemplate<int, int>[10]>)>::type)

But an even better way is to do the unpacking in the macro and clean up the
syntax:

struct pack;

template<class T> struct lock {
    typedef T type;
};

template<class T> struct unpack : lock<T> { };
template<> struct unpack<pack (void)> : lock<void> { };
template<class T> struct unpack<pack (T)> : lock<T> { };
template<class T> struct unpack<pack (lock<T>)> : lock<T> { };

#define MY_MACRO(t) ... unpack<t>::type ...

MY_MACRO( int )
MY_MACRO( pack (std::pair<int, int>) )
MY_MACRO( pack (lock<int[10]>) )

> IIUC this might be a problem if you need to be able to pass
> *any* type to a macro. But in the case of the serialization
> lib it's always a class type that needs to be registered. And
> neither void nor MyTemplate<int, int>[10] is a class type.
> Are you aware of any examples where above approach won't work
> when calling the serialization lib's export macros?

No, I was referring to the general problem.

> > > Whenever you have a macro that takes a classname you may
> face this
> > > issue. One could consider it a
> > > (inherent) preprocessor shortcoming solved by means of template
> > > programming.
> >
> > As an aside, if you have a conforming preprocessor, the problem is
> > solveable with the preprocessor (especially so with variadics).
>
> Is it solveable with the preprocessor as defined in the C++
> standard from 1998? Or do you need the C99 preprocessor?

It is solveable in C++ (though it is "prettier" in C99). Either way, it isn't
an option because it requires a very very conformant preprocessor.

Regards,
Paul Mensonides


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk