Thread overview
Question on Template Specializing.
Aug 07, 2013
SteveGuo
Aug 07, 2013
evilrat
Aug 07, 2013
Jesse Phillips
Aug 07, 2013
SteveGuo
Aug 07, 2013
evilrat
August 07, 2013
The following example can't be compiled.

// A.d
-------------------------------------

class A(T)
{
    T a;
}


// main.d
-------------------------------------
import A;

int main(string param[])
{
    A!(int) a;

    return 0;
}

Compiler complains with this message "Error: template instance A!(int) A is not a template declaration, it is a import"

So I read online documents, It says "TemplateInstantances are always performed in the scope of where the TemplateDeclaration is declared, with the addition of the template parameters being declared as aliases for their deduced types."

So, I modified the code as the following

// A.d
-------------------------------------

class A(T)
{
    T a;
}

alias A!(int) AInt;

// main.d
-------------------------------------
import A;

int main(string param[])
{
    AInt a;

    return 0;
}

This time it compiled successful.

But my question is:
If I am a library author, I write templates for my users, so users can specialize the template with any types they defined. I don't know what types they may define when I design the template, so how can I specialize the template for them in my template module?
August 07, 2013
On Wednesday, 7 August 2013 at 05:10:25 UTC, SteveGuo wrote:
> The following example can't be compiled.
>
> // A.d
> -------------------------------------
>
> class A(T)
> {
>     T a;
> }
>
>
> // main.d
> -------------------------------------
> import A;
>
> int main(string param[])
> {
>     A!(int) a;
>
>     return 0;
> }
>
> Compiler complains with this message "Error: template instance A!(int) A is not a template declaration, it is a import"
>
> So I read online documents, It says "TemplateInstantances are always performed in the scope of where the TemplateDeclaration is declared, with the addition of the template parameters being declared as aliases for their deduced types."
>
> So, I modified the code as the following
>
> // A.d
> -------------------------------------
>
> class A(T)
> {
>     T a;
> }
>
> alias A!(int) AInt;
>
> // main.d
> -------------------------------------
> import A;
>
> int main(string param[])
> {
>     AInt a;
>
>     return 0;
> }
>
> This time it compiled successful.
>
> But my question is:
> If I am a library author, I write templates for my users, so users can specialize the template with any types they defined. I don't know what types they may define when I design the template, so how can I specialize the template for them in my template module?

doh... most of such weird errors are due to module naming. module names should be always in lowercase(not neccessary but recommended), and the second, your problem is due to name conflict of module name and class name, just give your module a meaningful name and problem is gone.

why is that? i think because alias has tighter lookup rules than "normal" code.
August 07, 2013
On Wednesday, 7 August 2013 at 05:10:25 UTC, SteveGuo wrote:
> But my question is:
> If I am a library author, I write templates for my users, so users can specialize the template with any types they defined. I don't know what types they may define when I design the template, so how can I specialize the template for them in my template module?

if you want to make some presets for common types you can use aliases

alias A!int Aint;
alias A!float Afloat;
...

if you want to enforce template accept only certain types you should use static asserts or type covariance(oh sorry it's not called this but i'm somehow stupid now)

-------------
// type limitation with overloading
interface Something { ... }

// specialized template for covariants of Something(will be instantiated with any covariant of Something)
class A(T: Something) {
...
}

// generic template(instantiated when no specialized overloads exists)
class A(T) {

}
-------------
or static asserts/if
-------------
import std.traits;
class A(T) {
 // code for numeric types
 static if(isNumeric(T)) {
 ...
 }

 // code for callable objects
 static if(isCallable(T)) {

 }

 // and so on...
}
August 07, 2013
On Wednesday, 7 August 2013 at 05:31:07 UTC, evilrat wrote:
> On Wednesday, 7 August 2013 at 05:10:25 UTC, SteveGuo wrote:
>> The following example can't be compiled.
>>
>> // A.d
>> -------------------------------------
>>
>> class A(T)
>> {
>>    T a;
>> }
>>
>>
>> // main.d
>> -------------------------------------
>> import A;
>>
>> int main(string param[])
>> {
>>    A!(int) a;
>>
>>    return 0;
>> }
> doh... most of such weird errors are due to module naming. module names should be always in lowercase(not neccessary but recommended), and the second, your problem is due to name conflict of module name and class name, just give your module a meaningful name and problem is gone.

The name doesn't need to be changed, Instead main could have contain:

    A.A!(int) a;

Instantiate A from module A (instead of instantiate module A which is the cause of the error)
August 07, 2013
> The name doesn't need to be changed, Instead main could have contain:
>
>     A.A!(int) a;
>
> Instantiate A from module A (instead of instantiate module A which is the cause of the error)

Thanks, It was compiled successfully!