www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Forward declarations of template specilizations.

reply Ryan Bloomfield <_sir_maniacREMOVE_ME yahoo.com> writes:
I have an interesting issue, that makes me curious on how D handles it.

consider the following:
======================
module List;

template NodeTraits(NodeType)
{
	static NodeType getNext(NodeType v) { return v.next; }
}

class List(NodeType, Traits=NodeTraits!(NodeType))
{
	private NodeType head;

	
	NodeType next() { return Traits.getNext(head); }
}

======================
module main;

class Node {
	Node myNext;
}

template NodeTraits(NodeType : C)
{
	static NodeType getNext(NodeType v) { return v.myNext; }
}

main()
{
    	alias List!(Node) L;
	L l = new L();
	C next = l.next(); // error:  no property 'next' for type 'main.Node'
}
==============================================


  Templates are evaluated in the scope they are defined, which makes sense, but
when should the compiler check those definitions?  It makes sense that given 2
modules, one module shouldn't be able to change the behavior of another module,
having said that, c++ does allow this, and it proves very useful in customizing
the behavior of library classes.

  I noticed that if I change it to the following it works correctly(Traits
argument becomes an alias, and is passed in main):
======================
module List;

template NodeTraits(NodeType)
{
	static NodeType getNext(NodeType v) { return v.next; }
}

class List(NodeType, alias Traits)
{
	private NodeType head;

	
	NodeType next() { return Traits.getNext(head); }
}

======================
module main;

class Node {
	Node myNext;
}

template NodeTraits(NodeType : Node)
{
	static NodeType getNext(NodeType v) { return v.myNext; }
}

main()
{
       alias NodeTraits!(Node) Traits;  // a template's alias arguments only
take a single identifier
    	alias List!(Node, Traits) L;
	L l = new L();
	C next = l.next(); // Successfully accesses l.myNext
}
==============================================

Does the evaluation of a template have to know only the scope it was
instantiated in?  No forward declaration(of a module that imports it)?
Nov 14 2008
parent reply Christian Kamm <kamm-incasoftware removethis.de> writes:
 I have an interesting issue, that makes me curious on how D handles it.
 
 (Traits template code)
You cannot spread out template specializations across modules. If you define template Trait(T : S); in a.d and template Trait(T : C); in b.d and try to use alias Trait!(S) sinst; in use.d, you'll get Error: a.Trait(T : S) at a.d(3) conflicts with b.Trait(T : C) at b.d(3) because the two Traits live in separate scopes. This makes C++ style trait templates just not work in D. Does anyone know an equivalent?
Nov 16 2008
next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Sun, Nov 16, 2008 at 5:14 PM, Christian Kamm
<kamm-incasoftware removethis.de> wrote:
 I have an interesting issue, that makes me curious on how D handles it.

 (Traits template code)
You cannot spread out template specializations across modules. If you define template Trait(T : S); in a.d and template Trait(T : C); in b.d and try to use alias Trait!(S) sinst; in use.d, you'll get Error: a.Trait(T : S) at a.d(3) conflicts with b.Trait(T : C) at b.d(3) because the two Traits live in separate scopes. This makes C++ style trait templates just not work in D. Does anyone know an equivalent?
I think what Ryan said there is the general approach you have to take. Don't specialize the traits template, but rather pass in a whole new template as an alias parameter to the main template. This would be a good thing to add here: http://www.prowiki.org/wiki4d/wiki.cgi?PortingFromCxx Is there some canonical example of where you use specialized traits templates in C++? Or is this maybe a more general issue, like porting ADL code in C++. Not traits templates, but another ADL example is how you see IO done often in C++. With overloads for some common function like "write(Stream& o, ModuleSpecificType& val)". This pattern doesn't translate directly to D either. Suggestions? --bb
Nov 16 2008
parent reply Ryan Bloomfield <_sir_maniacREMOVE_ME yahoo.com> writes:
Bill Baxter Wrote:

 On Sun, Nov 16, 2008 at 5:14 PM, Christian Kamm
 <kamm-incasoftware removethis.de> wrote:
 I have an interesting issue, that makes me curious on how D handles it.

 (Traits template code)
You cannot spread out template specializations across modules. If you define template Trait(T : S); in a.d and template Trait(T : C); in b.d and try to use alias Trait!(S) sinst; in use.d, you'll get Error: a.Trait(T : S) at a.d(3) conflicts with b.Trait(T : C) at b.d(3) because the two Traits live in separate scopes. This makes C++ style trait templates just not work in D. Does anyone know an equivalent?
I think what Ryan said there is the general approach you have to take. Don't specialize the traits template, but rather pass in a whole new template as an alias parameter to the main template. This would be a good thing to add here: http://www.prowiki.org/wiki4d/wiki.cgi?PortingFromCxx Is there some canonical example of where you use specialized traits templates in C++? Or is this maybe a more general issue, like porting ADL code in C++. Not traits templates, but another ADL example is how you see IO done often in C++. With overloads for some common function like "write(Stream& o, ModuleSpecificType& val)". This pattern doesn't translate directly to D either. Suggestions? --bb
I think can understand why it works the way it does. ADL does sound a bit too complex(being hard to understand it's side-effect) to add to D. Polymorphism could be used as an alternative(the library class uses an interface to interact with the data), but that requires run-time overhead, but necessary anyway if polymorphism is involved in the data type. If I change the Traits from a template into a class template makes it easier to pass(no alias argument), the major difference is that the traits must be passed whenever it is overridden. According to http://www.digitalmars.com/d/1.0/templates-revisited.html(under "Template Parameters") a template can be passed as a template argument. How does one do that? The compiler (gdc) give an error when I try to pass a template like a type(complains it isn't a type). Ryan
Nov 16 2008
next sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Ryan Bloomfield wrote:
 According to http://www.digitalmars.com/d/1.0/templates-revisited.html(under
"Template Parameters") a template can be passed as a template argument.  How
does one do that? The compiler (gdc) give an error when I try to pass a
template like a type(complains it isn't a type).
Well, it's *not* a type, so that's understandable. It'll work as an alias parameter though.
Nov 16 2008
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sun, Nov 16, 2008 at 3:52 PM, Ryan Bloomfield
<_sir_maniacREMOVE_ME yahoo.com> wrote:
 According to http://www.digitalmars.com/d/1.0/templates-revisited.html(under
"Template Parameters") a template can be passed as a template argument.  How
does one do that? The compiler (gdc) give an error when I try to pass a
template like a type(complains it isn't a type).
You use an alias parameter instead of a type parameter. template A(alias Foo) { alias Foo!(int) A; } template B(T) { T B; } alias A!(B) x; // same as declaring "int x"
Nov 16 2008
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sun, Nov 16, 2008 at 3:14 AM, Christian Kamm
<kamm-incasoftware removethis.de> wrote:
 I have an interesting issue, that makes me curious on how D handles it.

 (Traits template code)
You cannot spread out template specializations across modules. If you define template Trait(T : S); in a.d and template Trait(T : C); in b.d and try to use alias Trait!(S) sinst; in use.d, you'll get Error: a.Trait(T : S) at a.d(3) conflicts with b.Trait(T : C) at b.d(3) because the two Traits live in separate scopes. This makes C++ style trait templates just not work in D. Does anyone know an equivalent?
Do D2's overload sets solve this, or are those for functions only?
Nov 16 2008