Limiting template functions to template instantiations of a struct

simendsjo simendsjo at gmail.com
Wed Nov 6 05:22:13 PST 2013


On Wednesday, 6 November 2013 at 13:00:17 UTC, Atila Neves wrote:
> The title isn't very clear but I wasn't sure how to phrase it 
> without code. Basically what I want to do is this (won't 
> compile):
>
> struct Foo(int N) {
> }
>
> void func(T)(T obj) if(is(T:Foo)) {
> }
>
> void func(T)(T obj) if(!is(T:Foo)) {
> }
>
> Foo by itself isn't a type, but I don't want to limit func 
> instantiation in the 1st case to just e.g. Foo!3 but to _any_ 
> Foo regardless of N. I came up with two workarouds: make Foo a 
> class that derives from an empty FooBase (then is(T:FooBase) 
> works), or adding a "secret" enum within Foo that I can check 
> with std.traits.hasMember in a static if. I don't really like 
> either of them. Is what I want to do possible?
>
> Atila

Here's a couple of different ways to do this.

     import std.stdio;

     struct Foo(int N) {
     }

     void func(T)(T obj) if(is(T:Foo!U, int U)) {
         writeln("It's a Foo!");
     }

     void func(T)(T obj) if(!is(T:Foo!U, int U)) {
         writeln("No Foo :(");
     }

     template isFoo(T) {
         static if(is(T:Foo!U, int U))
             enum isFoo = true;
         else
             enum isFoo = false;
     }

     void gunc(T)(T obj) if(isFoo!T) {
         writeln("Gunc isFoo");
     }

     void gunc(T)(T obj) if(!isFoo!T) {
         writeln("Gunc !isFoo");
     }

     void hunk(T)(T obj) {
         static if(isFoo!T)
             writeln("Hunk!");
         else
             writeln("No hunk!");
     }

     void main() {
         Foo!3 f;
         func(f); // It's a Foo!

         struct S {}
         S s;
         func(s); // No Foo :(

         gunc(f); // Gunc isFoo
         gunc(s); // Gunc !isFoo

         hunk(f); // Hunk!
         hunk(s); // No hunk!
     }


More information about the Digitalmars-d-learn mailing list