[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Types through a macro

niclas

11/28/2008 8:31:00 PM

Hello,

Assume:

template <typename A, typename B>
class C
{
};

#define MACRO(x) x

template <typename D>
class E
{
};

What I'd like to do is essentially the following:

E<MACRO(C<int, int>)> e;

However, now the comma inside the macro is interpreted as separating
macro parameters which results in an error. Ok, let us try to add
parentheses:

E<MACRO((C<int, int>))> e;

This get's rid of the earlier error but brings another one: the
declaration

E<(C<int, int>)> e;

is not legal C++.

Is there a way around?

Aside, it seems that
(C<int, int>) c;

is legal. What else can you do with parenthesized types?

--
http://kaba...
22 Answers

Andrey Tarasevich

11/28/2008 8:45:00 PM

0

Kaba wrote:
>
> What I'd like to do is essentially the following:
>
> E<MACRO(C<int, int>)> e;
>
> However, now the comma inside the macro is interpreted as separating
> macro parameters which results in an error. Ok, let us try to add
> parentheses:
>
> E<MACRO((C<int, int>))> e;
>
> This get's rid of the earlier error but brings another one: the
> declaration
>
> E<(C<int, int>)> e;
>
> is not legal C++.
>
> Is there a way around?

There is, but it is ugly to the point of being virtually unusable

#define ARGS C<int, int>
E<MACRO(ARGS)> e;
#undef ARGS

--
Best regards,
Andrey Tarasevich

niclas

11/28/2008 8:55:00 PM

0

Kaba wrote:
> Is there a way around?

Oh, I came up with a solution:

#define DEDUCTION(x) typename Deductor<void ##x>::Result

template <typename Type>
class Deductor
{
};

template <typename Type>
class Deductor<void (Type)>
{
public:
typedef Type Result;
};

template <int A, typename B>
class A
{
};

template <typename C>
class B
{
};

int main()
{
B<DEDUCTION((A<1, int>))> a;

return 0;
}

--
http://kaba...

niclas

11/28/2008 8:56:00 PM

0

Andrey Tarasevich wrote:
> There is, but it is ugly to the point of being virtually unusable
>
> #define ARGS C<int, int>
> E<MACRO(ARGS)> e;
> #undef ARGS

Thanks for your reply:)

--
http://kaba...

blargg.h4g

11/28/2008 9:46:00 PM

0

Kaba wrote:
> Kaba wrote:
> > Is there a way around?
>
> Oh, I came up with a solution:
>
> #define DEDUCTION(x) typename Deductor<void ##x>::Result
[...]

Why ##x instead of just x? Otherwise, clever solution to passing typenames
with commas in them to a macro!

niclas

11/28/2008 10:49:00 PM

0

blargg wrote:
> Kaba wrote:
> > Kaba wrote:
> > > Is there a way around?
> >
> > Oh, I came up with a solution:
> >
> > #define DEDUCTION(x) typename Deductor<void ##x>::Result
> [...]
>
> Why ##x instead of just x? Otherwise, clever solution to passing typenames
> with commas in them to a macro!

Thanks:) You are right, I removed it just after posting. Additionally, I
noticed that you can wrap the x into extra parentheses so that you need
not use double parentheses for simple types:

#define DEDUCTION(x) typename Deductor<void (x)>::Result

B<DEDUCTION((A<1, int>))> a;
B<DEDUCTION(int)> a;

I actually wrote this thing down here:

http://kaba.../Programming_C++/Texts/Templates_...

The thing that motivates me to search for this kind of solution is this:

http://kaba.../Programming_C++/Texts/Restricted_Ded...

--
http://kaba...

Gert-Jan de Vos

11/29/2008 8:12:00 AM

0

On Nov 28, 9:30 pm, Kaba <n...@here.com> wrote:
> ...
> What I'd like to do is essentially the following:
>
> E<MACRO(C<int, int>)> e;

Why not just:

typedef C<int, int> MyC;
E<MACRO(MyC)> e;

niclas

11/29/2008 9:27:00 AM

0

Gert-Jan de Vos wrote:
> On Nov 28, 9:30 pm, Kaba <n...@here.com> wrote:
> > ...
> > What I'd like to do is essentially the following:
> >
> > E<MACRO(C<int, int>)> e;
>
> Why not just:
>
> typedef C<int, int> MyC;
> E<MACRO(MyC)> e;

Because you have to be able to do it in a function declaration.. See the
link in my other post.

--
http://kaba...

courpron

11/29/2008 11:54:00 AM

0

On 28 nov, 23:48, Kaba <n...@here.com> wrote:
>
> The thing that motivates me to search for this kind of solution is this:
>
> http://kaba.hilvi.org/Programming_C++/Texts/Restricted_Ded...
>

I've quickly checked your article about restricted deduction.
It seems to me that there is a simple solution using type traits, that
resolves the problems you described.

From your "attempt 1 : direct templatization" :

template <typename Type>
class B
{
public:
B();

B<Type>& operator+=(Type value);
B<Type> operator+(Type value) const;

typedef Type type_trait;

private:
Type value_;
};

template <typename Type>
B<Type>::B()
: value_(0)
{
}

template <typename Type>
B<Type>& B<Type>::operator+=(Type value)
{
value_ += value;
return *this;
}

template <typename Type>
B<Type> B<Type>::operator+(Type value) const
{
B<Type> copy(*this);
copy += value;
return copy;
}

template <typename Type>
B<Type> operator+(typename B<Type>::type_trait value, const B<Type>&
that)
{
// Assuming symmetric addition
return that + value;
}

int main()
{
B<float> b;

b = b + 1;
b = 1 + b;

return 0;
}


Alexandre Courpron.

niclas

11/29/2008 12:32:00 PM

0

wrote:
> On 28 nov, 23:48, Kaba <n...@here.com> wrote:
> >
> > The thing that motivates me to search for this kind of solution is this:
> >
> > http://kaba.../Programming_C++/Texts/Restricted_Ded...
> >
>
> I've quickly checked your article about restricted deduction.
> It seems to me that there is a simple solution using type traits, that
> resolves the problems you described.

Yep, it is essentially the attempt 4 on the article. However, using a
separate Identity metafunction is more generic.

--
http://kaba...

courpron

11/29/2008 2:29:00 PM

0

On 29 nov, 13:32, Kaba <n...@here.com> wrote:
>  wrote:
> > On 28 nov, 23:48, Kaba <n...@here.com> wrote:
>
> > > The thing that motivates me to search for this kind of solution is this:
>
> > >http://kaba.hilvi.org/Programming_C++/Texts/Restricted_Ded...
>
> > I've quickly checked your article about restricted deduction.
> > It seems to me that there is a simple solution using type traits, that
> > resolves the problems you described.
>
> Yep, it is essentially the attempt 4 on the article.

Yes, I read too quickly and I didn't see that attempt. It is indeed
rather similar to what I proposed.

> However, using a separate Identity metafunction is more generic.

Question is : " does we really need this generecity, since we control
the declaration of the class ?"

Generally, you use the identity function from a library, boost for
example (otherwise the "identity" solution is obviously the worst one
since you have to declare the identity structure each time).

So the identity solution requires :
-including the header :
#include "...."

- taking care of the namespace of identity :
boost::mpl::identity<...>


On the other hand, the type_trait solution just need a nested
typedef :
typedef Type type_trait;

Since a typedef is as short and as simple as an inclusion of a file,
generecity doesn't bring here anything in terms of DRY (don't repeat
yourself) ; except if you already include that header because, by
chance, your class needs elsewhere the identity structure or any other
structure present in the header.

It seems that, with the identity solution, you have to write more
code, you depend on an external structure and on an (additional)
library, and you put more stress on the compiler.

Note that this can be more of a general debate about the (abusive) use
of generic code.


Alexandre Courpron.