www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Limiting template functions to template instantiations of a struct

reply "Atila Neves" <atila.neves gmail.com> writes:
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
Nov 06 2013
next sibling parent reply "Namespace" <rswhite4 googlemail.com> writes:
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
This works: http://dpaste.dzfl.pl/f98f4783
Nov 06 2013
parent reply "Atila Neves" <atila.neves gmail.com> writes:
Wow. It didn't even occur to me that `is` could be used like 
that. I think that operator is the hardest part of the language 
for me to grok. Thanks guys!
Nov 06 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 6 November 2013 at 21:49:52 UTC, Atila Neves wrote:
 Wow. It didn't even occur to me that `is` could be used like 
 that. I think that operator is the hardest part of the language 
 for me to grok. Thanks guys!
http://dlang.org/expression.html#IsExpression ;)
Nov 06 2013
parent reply "Atila Neves" <atila.neves gmail.com> writes:
On Wednesday, 6 November 2013 at 21:52:04 UTC, Dicebot wrote:
 On Wednesday, 6 November 2013 at 21:49:52 UTC, Atila Neves 
 wrote:
 Wow. It didn't even occur to me that `is` could be used like 
 that. I think that operator is the hardest part of the 
 language for me to grok. Thanks guys!
http://dlang.org/expression.html#IsExpression ;)
I know, but I keep having to refer back to that and even then I didn't know about the syntax these guys just posted! ;)
Nov 06 2013
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 6 November 2013 at 22:41:08 UTC, Atila Neves wrote:
 I know, but I keep having to refer back to that and even then I 
 didn't know about the syntax these guys just posted! ;)
Well, it is mentioned in the list of `is` usage cases down that link. It is very ugly part of the language but definitely worth spending some time to carefully investigate all the patterns - damn powerful stuff.
Nov 06 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Wednesday, 6 November 2013 at 22:43:18 UTC, Dicebot wrote:
 On Wednesday, 6 November 2013 at 22:41:08 UTC, Atila Neves 
 wrote:
 I know, but I keep having to refer back to that and even then 
 I didn't know about the syntax these guys just posted! ;)
Well, it is mentioned in the list of `is` usage cases down that link. It is very ugly part of the language but definitely worth spending some time to carefully investigate all the patterns - damn powerful stuff.
There are so much more uglier things ... :P Take a look at the scoped or ref counted implementation.
Nov 06 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Nov 06, 2013 at 11:52:56PM +0100, Namespace wrote:
 On Wednesday, 6 November 2013 at 22:43:18 UTC, Dicebot wrote:
On Wednesday, 6 November 2013 at 22:41:08 UTC, Atila Neves wrote:
I know, but I keep having to refer back to that and even then I
didn't know about the syntax these guys just posted! ;)
Well, it is mentioned in the list of `is` usage cases down that link. It is very ugly part of the language but definitely worth spending some time to carefully investigate all the patterns - damn powerful stuff.
There are so much more uglier things ... :P Take a look at the scoped or ref counted implementation.
Are you sure about that? Do you know that this does? int func(ref int x, string y, float z = 3.14159) { ... } // This is possibly the single nastiest bit of syntax in all of D: static if (is(func X == __parameters)) { // Quick, without looking at the docs: what does X refer // to? // If you manage to figure that one out, can you say // with certainty what's the type of X? Are you sure? :P alias Y = X[0]; // Quick, without looking at the docs: what is Y? // (If your answer was, the first element of X, you're // wrong!) // Quiz: how do you get a single element of X? (And no, // X[i] is the wrong answer, see above.) // If you got it right thus far: how do you access the // name of a single element of X? The default value? // (Note: if you didn't get the previous questions // right, don't even attempt this one; it's one of those // things that nobody can possibly guess unless they've // seen it before.) } Almost every part of the above is so completely counterintuitive and impossible to predict from the syntax that I honestly doubt if the scoped or RefCounted implementation could beat it for ugliness. :P T -- Notwithstanding the eloquent discontent that you have just respectfully expressed at length against my verbal capabilities, I am afraid that I must unfortunately bring it to your attention that I am, in fact, NOT verbose.
Nov 06 2013
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/07/2013 12:07 AM, H. S. Teoh wrote:
 	// This is possibly the single nastiest bit of syntax in all of D:
 	static if (is(func X == __parameters)) {
 		// Quick, without looking at the docs: what does X refer
 		// to?
Nothing.
Nov 07 2013
prev sibling parent reply "simendsjo" <simendsjo gmail.com> writes:
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! }
Nov 06 2013
parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Wed, 06 Nov 2013 14:22:13 +0100
schrieb "simendsjo" <simendsjo gmail.com>:

      template isFoo(T) {
          static if(is(T:Foo!U, int U))
              enum isFoo = true;
          else
              enum isFoo = false;
      }
enum isFoo(T) = is(T:Foo!U, int U); correct ? -- Marco
Nov 07 2013
parent "simendsjo" <simendsjo gmail.com> writes:
On Thursday, 7 November 2013 at 15:46:53 UTC, Marco Leise wrote:
 Am Wed, 06 Nov 2013 14:22:13 +0100
 schrieb "simendsjo" <simendsjo gmail.com>:

      template isFoo(T) {
          static if(is(T:Foo!U, int U))
              enum isFoo = true;
          else
              enum isFoo = false;
      }
enum isFoo(T) = is(T:Foo!U, int U); correct ?
I haven't tried 2.064 yet, but that should be correct. I'll be able to shave away a whole lot of "useless" lines because of this. And the strange thing is that I didn't even know about this enhancement before reading the changelog.
Nov 07 2013