www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - tuple parameter fwd

reply "kdmult" <kdmult ya.ru> writes:
Hi,

I would like to use a tuple template parameter in the default 
value of another template parameter in the same class declaration 
as follows.

class A(P...) {}

class B(R = A!P, P...) {}

P... should be rightmost, so how can I use it in the preceding 
parameter?

Thanks.
Aug 05 2013
next sibling parent reply "kdmult" <kdmult ya.ru> writes:
On Monday, 5 August 2013 at 18:45:49 UTC, kdmult wrote:
 class A(P...) {}

 class B(R = A!P, P...) {}

 P... should be rightmost, so how can I use it in the preceding 
 parameter?
The default parameter value doesn't make sense as it's shown above. Actually I want to port C++ code which looks like below. template <typename P1> class A1 {}; template <typename P1, typename R=A1<P1> > class B1 {} template <typename P1, typename P2> class A2 {}; template <typename P1, typename P2, typename R=A2<P1,P2> > class B2 {} and so on. I would use the variadic template parameters. However, I have no idea how it can be done. Please advise. Thanks.
Aug 05 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/05/2013 09:51 PM, kdmult wrote:
 On Monday, 5 August 2013 at 18:45:49 UTC, kdmult wrote:
 class A(P...) {}

 class B(R = A!P, P...) {}

 P... should be rightmost, so how can I use it in the preceding parameter?
The default parameter value doesn't make sense as it's shown above. Actually I want to port C++ code which looks like below. template <typename P1> class A1 {}; template <typename P1, typename R=A1<P1> > class B1 {} template <typename P1, typename P2> class A2 {}; template <typename P1, typename P2, typename R=A2<P1,P2> > class B2 {} and so on. I would use the variadic template parameters. However, I have no idea how it can be done. Please advise. Thanks.
Direct translation seems to work: class A1(P1) {} class B1(P1, R = A1!P1) {} class A2(P1, P2) {} class B2(P1, P2, R = A2!(P1, P2)) {} void main() { auto a1 = new A1!int; auto b1d = new B1!int; auto b1 = new B1!(int, A1!double); auto a2 = new A2!(int, double); auto b2d = new B2!(int, double); auto b2 = new B2!(int, double, A2!(char, short)); } Ali
Aug 05 2013
parent "kdmult" <kdmult ya.ru> writes:
On Tuesday, 6 August 2013 at 05:07:51 UTC, Ali Çehreli wrote:
 On 08/05/2013 09:51 PM, kdmult wrote:
 On Monday, 5 August 2013 at 18:45:49 UTC, kdmult wrote:
 class A(P...) {}

 class B(R = A!P, P...) {}

 P... should be rightmost, so how can I use it in the 
 preceding parameter?
The default parameter value doesn't make sense as it's shown above. Actually I want to port C++ code which looks like below. template <typename P1> class A1 {}; template <typename P1, typename R=A1<P1> > class B1 {} template <typename P1, typename P2> class A2 {}; template <typename P1, typename P2, typename R=A2<P1,P2> > class B2 {} and so on. I would use the variadic template parameters. However, I have no idea how it can be done. Please advise. Thanks.
Direct translation seems to work: class A1(P1) {} class B1(P1, R = A1!P1) {} class A2(P1, P2) {} class B2(P1, P2, R = A2!(P1, P2)) {} void main() { auto a1 = new A1!int; auto b1d = new B1!int; auto b1 = new B1!(int, A1!double); auto a2 = new A2!(int, double); auto b2d = new B2!(int, double); auto b2 = new B2!(int, double, A2!(char, short)); } Ali
Is there a way to use variadic template/class parameter instead of P1, P2, ..., PN ? If it is I could create 2 templated classes instead of all that copy/pasted classes with P1, P2, etc parameters. Thanks.
Aug 05 2013
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 08/05/2013 11:45 AM, kdmult wrote:

 Hi,

 I would like to use a tuple template parameter in the default value of
 another template parameter in the same class declaration as follows.

 class A(P...) {}

 class B(R = A!P, P...) {}

 P... should be rightmost, so how can I use it in the preceding parameter?

 Thanks.
Do you mean that when P[0] is already an instance of A, then R should be P[0]. Otherwise, R should be A!P? If so, the following works: class A(P...) { pragma(msg, "\nA: " ~ P.stringof); } class BImpl(R, P...) { pragma(msg, "R: " ~ R.stringof ~ ", P: " ~ P.stringof); } template B(P...) { static if (is (P[0] == A!U, U)) { /* The first type is already an A instance. Accept the types as is. */ alias B = BImpl!P; } else { /* The first type is not an A instance. Inject one. */ alias B = BImpl!(A!P, P); } } void main() { auto b0 = new B!(int, double, char); auto b1 = new B!(A!long, int, double); } Ali
Aug 06 2013
parent "kdmult" <kdmult ya.ru> writes:
On Tuesday, 6 August 2013 at 09:53:33 UTC, Ali Çehreli wrote:
 Do you mean that when P[0] is already an instance of A, then R 
 should be P[0]. Otherwise, R should be A!P? If so, the 
 following works:

 class A(P...)
 {
     pragma(msg, "\nA: " ~ P.stringof);
 }

 class BImpl(R, P...)
 {
     pragma(msg, "R: " ~ R.stringof ~ ", P: " ~ P.stringof);
 }

 template B(P...)
 {
     static if (is (P[0] == A!U, U)) {
         /* The first type is already an A instance. Accept the 
 types as is. */
         alias B = BImpl!P;

     } else {
         /* The first type is not an A instance. Inject one. */
         alias B = BImpl!(A!P, P);
     }
 }

 void main()
 {
     auto b0 = new B!(int, double, char);
     auto b1 = new B!(A!long, int, double);
 }

 Ali
Great! Thanks Ali.
Aug 06 2013
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 08/05/13 20:45, kdmult wrote:
 Hi,
 
 I would like to use a tuple template parameter in the default value of another
template parameter in the same class declaration as follows.
 
 class A(P...) {}
 
 class B(R = A!P, P...) {}
 
 P... should be rightmost, so how can I use it in the preceding parameter?
If you don't need to specify R explicitly just add an alias R = A!P; inside B. Otherwise, you'll have to manually determine whether R was given - it's not possible to automatically tell if the first B parm is: a) R, or b) the first element of P. For example: class B(_P...) { static if (is(_P[0] _ == A!TP, TP...)) { alias R = _P[0]; alias P = _P[1..$]; } else { alias R = A!P; alias P = _P; } //... } artur
Aug 05 2013