Jump to page: 1 2
Thread overview
D's limited template specialization abilities compared to C++
May 25, 2013
Ahuzhgairl
May 25, 2013
Ahuzhgairl
May 25, 2013
Peter Alexander
May 25, 2013
Ahuzhgairl
May 25, 2013
Ahuzhgairl
May 25, 2013
Peter Alexander
May 25, 2013
Kenji Hara
May 25, 2013
Ahuzhgairl
May 25, 2013
Peter Alexander
May 25, 2013
Kenji Hara
May 25, 2013
Ahuzhgairl
May 26, 2013
Kenji Hara
May 26, 2013
Ahuzhgairl
May 26, 2013
Manu
May 26, 2013
Andrej Mitrovic
May 26, 2013
Timon Gehr
May 27, 2013
Andrej Mitrovic
May 25, 2013
deadalnix
May 25, 2013
Joshua Niehus
May 25, 2013
Hi,

In D, the : in a template parameter list only binds to 1 parameter.
There is no way to specialize upon the entire template parameter list.
Therefore you can't do much with the pattern matching and it's not powerful.
Not a reasonable situation for a language aiming to be only the best.

What is needed is the ability to bind to the whole template parameter list:

template <class> struct get_class;
template <class R, class C, class... A> struct get_class<R (C::*)(A...)> { typedef C type; };

Let's shorten the terms:

<R, C, A...> @ <R (C::*)(A...)>

And here's how this kind of specialization would work in D:

template A[B] { struct C {} } template Foo[alias X, Y, Z @ X[Y].Z] { alias Z Foo; } void main() { alias Foo[A[bool].C] xxx; }

You need a separate delimiter besides : which does not bind to individual parameters, but which binds to the set of parameters.

I propose @ as the character which shall be the delimiter for the arguments to the pattern match, and the pattern match.

On an unrelated note, I don't like the ! thing so I use []. Sorry for the confusion there.

z
May 25, 2013
By extension,

template Foo[X, Y, Z @ X[Y], Y[Z]] { alias Y Foo; }
May 25, 2013
Is this what you're looking for?

struct Foo(T)
{
	static void bar() { writeln("general"); }
}

struct Foo(T : A[B], A, B)
{
	static void bar() { writeln("special"); }
}

void main()
{
	Foo!(int).bar(); // general
	Foo!(int[int]).bar(); // special
}
May 25, 2013
No,




struct Foo(T) {
    static void f() { writeln("general"); }
}

struct Foo(T : A(B).alias C, A, B, C) {
    static void f() { writeln("special"); }
}

struct Bar(T) {
    struct Baz {}
}

struct Baz(T : A(B), A, B) {
}

void main() {
    Foo!(Bar!(int).Baz);
    Baz!(Bar!(int));
}
May 25, 2013
Uneditable newsgroups. Simplest case.

struct Bar(T) {}

struct Foo(T : A(B), A, B) {
    static void f() {}
}

void main() {
    Foo!(Bar!(int)).f();
}
May 25, 2013
On Saturday, 25 May 2013 at 12:13:42 UTC, Ahuzhgairl wrote:
> Uneditable newsgroups. Simplest case.
>
> struct Bar(T) {}
>
> struct Foo(T : A(B), A, B) {
>     static void f() {}
> }
>
> void main() {
>     Foo!(Bar!(int)).f();
> }

Two problems with that:

1. A(B) should be A!(B)
2. A won't bind to Bar because Bar is not a type, it is a template. A should be an alias.

This works:

struct Bar(T) {}

struct Foo(T : A!(B), alias A, B) {
    static void f() {}
}

void main() {
    Foo!(Bar!(int)).f();
}
May 25, 2013
2013/5/25 Ahuzhgairl <bulletproofchest@gmail.com>

> Uneditable newsgroups. Simplest case.
>
> struct Bar(T) {}
>
> struct Foo(T : A(B), A, B) {
>     static void f() {}
> }
>
> void main() {
>     Foo!(Bar!(int)).f();
> }
>

It would work.

struct Bar(T) {}
struct Foo(T : A!(B), alias A, B) {   // 1, 2
    static void f() {}
}
void main() {
    Foo!(Bar!(int)).f();
}

1. should use A!(B), instead of A(B)
2. A would match to template, so should receive by TemplateAliasParameter.

Kenji Hara


May 25, 2013
C++ example, works:

template <class> struct A;
template <template <class> class X, class Y> struct A<X<Y>> {};

template <class> struct B;

int main() {
    A<B<int>> a;
}



But the following does not work:

struct Foo {};
template <class> struct B { Foo x; }

template <nontype P> struct A;
template <auto M, auto C, nontype P> struct A<M C::*P> {}

int main() {
    A<&B<int>::x> a;
}


D should be able to do both.
May 25, 2013
On Saturday, 25 May 2013 at 12:43:42 UTC, Ahuzhgairl wrote:
> C++ example, works:
>
> template <class> struct A;
> template <template <class> class X, class Y> struct A<X<Y>> {};
>
> template <class> struct B;
>
> int main() {
>     A<B<int>> a;
> }

As we've shown, you can do this in D. Instead of template templates, you use alias.


> But the following does not work:
>
> struct Foo {};
> template <class> struct B { Foo x; }
>
> template <nontype P> struct A;
> template <auto M, auto C, nontype P> struct A<M C::*P> {}
>
> int main() {
>     A<&B<int>::x> a;
> }

It's getting very hard to see what you're trying to do. I think it would help if you used real C++ and D syntax instead of inventing new syntax because I can't tell what you're trying to achieve and what semantics you expect of it.

Please post a small example of real, working, compilable C++ that shows what you want to do, and we'll show you how to do it in D (assuming it is possible).
May 25, 2013
2013/5/25 Ahuzhgairl <bulletproofchest@gmail.com>

> No,
>
> struct Foo(T) {
>     static void f() { writeln("general"); }
> }
>
> struct Foo(T : A(B).alias C, A, B, C) {
>     static void f() { writeln("special"); }
> }
>
> struct Bar(T) {
>     struct Baz {}
> }
>
> struct Baz(T : A(B), A, B) {
> }
>
> void main() {
>     Foo!(Bar!(int).Baz);
>     Baz!(Bar!(int));
> }
>

As I already shown, Baz!(Bar!(int)); could work in D.

But, currently Foo!(Bar!(int).Baz); is not yet supported.

I'm opening a compiler enhancement for related case, http://d.puremagic.com/issues/show_bug.cgi?id=9022

and right now I updated compiler patch to allow parameterize enclosed type
by name/type/alias.
https://github.com/D-Programming-Language/dmd/pull/1296
https://github.com/9rnsr/dmd/commit/b29726d30b0094b9e7c2e15f5802501cb686ee68

After it is merged, you can write it as follows.

import std.stdio;
struct Foo(T)
{
    static void f() { writeln("general"); }
}
struct Foo(T : A!(B).C, alias A, B, alias C)
{
    static void f() { writeln("special"); }
}

struct Bar(T) { struct Baz {} }

void main()
{
    Foo!(Bar!(int).Baz) x;
    x.f();  // prints "special"
}

Kenji Hara


« First   ‹ Prev
1 2