Difference between revisions of "DIP40"

From D Wiki
Jump to: navigation, search
(Example)
 
(3 intermediate revisions by the same user not shown)
Line 50: Line 50:
 
<syntaxhighlight lang="d">
 
<syntaxhighlight lang="d">
 
struct A(T1)
 
struct A(T1)
if(!is(T1==float))
+
if(isNumeric!T1 && !is(T1==float))
 
{
 
{
 
this(T2) if(!isNumeric!T2) (T2 a, T1 b){}
 
this(T2) if(!isNumeric!T2) (T2 a, T1 b){}
Line 57: Line 57:
 
}
 
}
 
struct A(T1)
 
struct A(T1)
if(is(T1==float))
+
if(isNumeric!T1 && is(T1==float))
 
{
 
{
 
this()(){}
 
this()(){}
 +
}
 +
struct A(T1)
 +
if (!isNumeric!T1)
 +
{
 +
    this()(T1 a) {}
 
}
 
}
 +
 +
template foo(T3){
 +
struct A(T1){ //not in scope
 +
    this()(T1 a) {}
 +
}
 +
}
 +
 +
template A(T1){
 +
struct A{ //not in scope unless T1 is explicitly instantiated
 +
    this()(T1 a) {}
 +
}
 +
}
 +
 +
static if(false){
 +
struct A(T1){//not in scope
 +
    this()(T1 a) {}
 +
}
 +
}
 +
  
 
auto a=A(1,1.0); //deduced to A!(double)(1,1.0)
 
auto a=A(1,1.0); //deduced to A!(double)(1,1.0)
Line 68: Line 92:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
== Deduction ==
 +
Step 1)
 +
Find all matching class/struct types in scope, temporarily ignoring the template constraints (the 3 struct A definitions in our example)
 +
 +
Step 2)
 +
For each type in step 1, find all constructors, temporarily ignoring the template constraints (3 + 1 + 1 in our example)
 +
 +
Step 3)
 +
This constitutes our overload set.
 +
For each element in the overload set,
 +
* form list of template parameters that is the concatenation of the ones in the type and the ones in the constructor (in our example, the 1st one has 2 template parameters (T1,T2) and all the others have 1).
 +
* form list of template constraints as a logical AND of the ones in the type and the ones in the constructor
 +
With this transformation, the problem is now the same as for template deduction of normal functions: we apply the usual template deduction rules are used, taking into account the number of parameters and compatibility of template constraints.
  
== Deduction ==
+
Step 4)
An overload set of constructors is formed containing all possible matching class/struct types with their template constraints (the 2 struct A definitions here) + constructors for each of those types. In our examples, this yields 3 + 1 = 4 constructors.
 
Then the usual template deduction rules are used, taking into account the template constraints from the class/struct types and the ones from the constructors (as for normal functions).
 
 
If there is an ambiguity or no match, give an error, otherwise instantiate.
 
If there is an ambiguity or no match, give an error, otherwise instantiate.
  

Latest revision as of 07:25, 14 May 2013

DIP 40: Template parameter deduction for constructors

Title: Template parameter deduction for constructors.
DIP: 40
Version: 1
Status: Draft
Created: 2013-05-12
Last Modified: 2013-05-12
Author: Timothee Cour
Links:

Abstract

A proposed feature of C++14 is to introduce template parameter deduction for constructors, see paper, mentioned here. The idea is to deduce template parameters when calling a constructor given the arguments given to the constructor, whenever possible. A compile error occurs when the deduction is ambiguous. The benefits would be:

  • make the code more DRY
  • make boilerplate of class instantiators unnecessary in most cases (they're all over phobos, eg: std.typecons.tuple, std.typecons.rebindable etc)
  • make D more consistent: it deduces template parameters for functions, so why not for constructors, when this is unambiguous?
  • it won't break any code.

Note, just as for deduction of normal functions, it should work with 0 or more template parameters specified (ie the first k>=0 templates may be provided).

Example

import std.typecons;
auto a=Tuple!(int, double)(1,1.0); //not DRY
auto a=tuple(1,1.0); //boilerplate in std.typecons: requires auxiliary class instantiator function 'tuple' just to allow this
auto a=Tuple(1,1.0); //proposed syntax that deduces type parameters

Another example:

struct A(T1)
if(isNumeric!T1 && !is(T1==float))
{
	this(T2) if(!isNumeric!T2) (T2 a, T1 b){}
	this()(T1 b){}
	this()(){}
}
struct A(T1)
if(isNumeric!T1 && is(T1==float))
{
	this()(){}
}
struct A(T1)
if (!isNumeric!T1)
{
    this()(T1 a) {}
}

template foo(T3){
struct A(T1){ //not in scope
    this()(T1 a) {}
}
}

template A(T1){
struct A{ //not in scope unless T1 is explicitly instantiated
    this()(T1 a) {}
}
}

static if(false){ 
struct A(T1){//not in scope
    this()(T1 a) {}
}
}


auto a=A(1,1.0); //deduced to A!(double)(1,1.0)
auto a=A(1.0); //deduced to A!(double)(1.0)
auto a=A(); //error: T1 cannot be deduced.
auto a=A(Object.init,1.0); //error: no matching type

Deduction

Step 1) Find all matching class/struct types in scope, temporarily ignoring the template constraints (the 3 struct A definitions in our example)

Step 2) For each type in step 1, find all constructors, temporarily ignoring the template constraints (3 + 1 + 1 in our example)

Step 3) This constitutes our overload set. For each element in the overload set,

  • form list of template parameters that is the concatenation of the ones in the type and the ones in the constructor (in our example, the 1st one has 2 template parameters (T1,T2) and all the others have 1).
  • form list of template constraints as a logical AND of the ones in the type and the ones in the constructor

With this transformation, the problem is now the same as for template deduction of normal functions: we apply the usual template deduction rules are used, taking into account the number of parameters and compatibility of template constraints.

Step 4) If there is an ambiguity or no match, give an error, otherwise instantiate.

Extension

A possible extension is to also allow template parameter deduction for static functions, using the same mechanism as for templates.

Copyright

This document has been placed in the Public Domain.