Thread overview
class specialization for integral types
Sep 24, 2011
Charles Hixson
Sep 24, 2011
Jonathan M Davis
Sep 24, 2011
Charles Hixson
Sep 24, 2011
Jonathan M Davis
Sep 25, 2011
Charles Hixson
Sep 25, 2011
Charles Hixson
Sep 25, 2011
Jonathan M Davis
Sep 25, 2011
Charles Hixson
Sep 25, 2011
Charles Hixson
Sep 25, 2011
Jonathan M Davis
September 24, 2011
How would a specialize a parameterized class to only allow integral parameters (i.e., anything that would respond "true" to
static if (is (T : long) )

(I'd have said "static if (is (T : cent) )" or "static if (is (T : ucent) )", but those are still marked "reserved for future use".)

I do want to allow byte, ubyte, etc. to be legal values.
September 24, 2011
On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
> How would a specialize a parameterized class to only allow integral
> parameters (i.e., anything that would respond "true" to
> static if (is (T : long) )
> 
> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
> ucent) )", but those are still marked "reserved for future use".)
> 
> I do want to allow byte, ubyte, etc. to be legal values.

Parameterized? As in templated? Just use a template constraint.

class C(T)
    if(is(T : long))
{
}

T will then be allowed to be anything which is implicitly convertible to long. I'd suggest using std.traits.isIntegral instead though.

class C(T)
    if(isIntegral!T)
{
}

It specifically tests for whether the type is a byte, ubyte, short, ushort, int, uint, long, or ulong, so it won't included stray structs or classes which would be implicitly convertible to long, and if/when eont and ucent come along, they'd be added to isIntegral and be automatically supported.

- Jonathan M Davis
September 24, 2011
On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>> How would a specialize a parameterized class to only allow integral
>> parameters (i.e., anything that would respond "true" to
>> static if (is (T : long) )
>>
>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>> ucent) )", but those are still marked "reserved for future use".)
>>
>> I do want to allow byte, ubyte, etc. to be legal values.
>
> Parameterized? As in templated? Just use a template constraint.
>
> class C(T)
>      if(is(T : long))
> {
> }
>
> T will then be allowed to be anything which is implicitly convertible to long.
> I'd suggest using std.traits.isIntegral instead though.
>
> class C(T)
>      if(isIntegral!T)
> {
> }
>
> It specifically tests for whether the type is a byte, ubyte, short, ushort,
> int, uint, long, or ulong, so it won't included stray structs or classes which
> would be implicitly convertible to long, and if/when eont and ucent come
> along, they'd be added to isIntegral and be automatically supported.
>
> - Jonathan M Davis

Thanks.  isIntegral has given me some error messages that I couldn't understand, though, so I'll take your first suggestion.

This is actually a rephrase of the question I first sent, when somehow didn't appear on the list:

When checking a template variable, what are the base cases for is?
long will satisfy all integer types.  I.e.
  is (typeof(tst0) : long)  == true
real will satisfy all floating point types.
I think that string will satisfy all arrays of characters (need to check that).

But there are lots of other kinds of array.  And while Object will satisfy all classes, I don't know anything analogous for structs.  Then there's enums (would they be caught by their base type as above, or with they be like string and require an immutable corresponding to the base type?

I'd like to create a chunk of code that will handle all possible types (for a particular operation) but how to do this isn't obvious.  I can handle most common types, but there seem to be LOTS of less frequent types.


September 24, 2011
On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
> > On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
> >> How would a specialize a parameterized class to only allow integral
> >> parameters (i.e., anything that would respond "true" to
> >> static if (is (T : long) )
> >> 
> >> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
> >> ucent) )", but those are still marked "reserved for future use".)
> >> 
> >> I do want to allow byte, ubyte, etc. to be legal values.
> > 
> > Parameterized? As in templated? Just use a template constraint.
> > 
> > class C(T)
> > 
> >      if(is(T : long))
> > 
> > {
> > }
> > 
> > T will then be allowed to be anything which is implicitly convertible to long. I'd suggest using std.traits.isIntegral instead though.
> > 
> > class C(T)
> > 
> >      if(isIntegral!T)
> > 
> > {
> > }
> > 
> > It specifically tests for whether the type is a byte, ubyte, short, ushort, int, uint, long, or ulong, so it won't included stray structs or classes which would be implicitly convertible to long, and if/when eont and ucent come along, they'd be added to isIntegral and be automatically supported.
> > 
> > - Jonathan M Davis
> 
> Thanks.  isIntegral has given me some error messages that I couldn't understand, though, so I'll take your first suggestion.
> 
> This is actually a rephrase of the question I first sent, when somehow didn't appear on the list:
> 
> When checking a template variable, what are the base cases for is?
> long will satisfy all integer types.  I.e.
>    is (typeof(tst0) : long)  == true
> real will satisfy all floating point types.
> I think that string will satisfy all arrays of characters (need to check
> that).
> 
> But there are lots of other kinds of array.  And while Object will
> satisfy all classes, I don't know anything analogous for structs.  Then
> there's enums (would they be caught by their base type as above, or with
> they be like string and require an immutable corresponding to the base type?
> 
> I'd like to create a chunk of code that will handle all possible types (for a particular operation) but how to do this isn't obvious.  I can handle most common types, but there seem to be LOTS of less frequent types.

You really should look at std.traits. It has that sort of stuff in it. It's what you should be using for really general stuff. Unqual, isDynamicArray, isFloatingPoint, etc. are all the sorts of things that you should be using for general tests on types.

is(T == U) is going to be true if T and U are exactly the same type.

is(T : U) is going to be true if T is implicitly convertible to U.

If all that you care about is class or struct, then you can use

is(T == class)
is(T == struct)

You should also look at http://www.d-programming-language.org/traits.html.

- Jonathan M Davis
September 25, 2011
On 09/24/2011 04:31 PM, Jonathan M Davis wrote:
> On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
>> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
>>> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>>>> How would a specialize a parameterized class to only allow integral
>>>> parameters (i.e., anything that would respond "true" to
>>>> static if (is (T : long) )
>>>>
>>>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>>>> ucent) )", but those are still marked "reserved for future use".)
>>>>
>>>> I do want to allow byte, ubyte, etc. to be legal values.
>>>
>>> Parameterized? As in templated? Just use a template constraint.
>>>
>>> class C(T)
>>>
>>>       if(is(T : long))
>>>
>>> {
>>> }
>>>
>>> T will then be allowed to be anything which is implicitly convertible to
>>> long. I'd suggest using std.traits.isIntegral instead though.
>>>
>>> class C(T)
>>>
>>>       if(isIntegral!T)
>>>
>>> {
>>> }
>>>
>>> It specifically tests for whether the type is a byte, ubyte, short,
>>> ushort, int, uint, long, or ulong, so it won't included stray structs
>>> or classes which would be implicitly convertible to long, and if/when
>>> eont and ucent come along, they'd be added to isIntegral and be
>>> automatically supported.
>>>
>>> - Jonathan M Davis
>>
>> Thanks.  isIntegral has given me some error messages that I couldn't
>> understand, though, so I'll take your first suggestion.
>>
>> This is actually a rephrase of the question I first sent, when somehow
>> didn't appear on the list:
>>
>> When checking a template variable, what are the base cases for is?
>> long will satisfy all integer types.  I.e.
>>     is (typeof(tst0) : long)  == true
>> real will satisfy all floating point types.
>> I think that string will satisfy all arrays of characters (need to check
>> that).
>>
>> But there are lots of other kinds of array.  And while Object will
>> satisfy all classes, I don't know anything analogous for structs.  Then
>> there's enums (would they be caught by their base type as above, or with
>> they be like string and require an immutable corresponding to the base type?
>>
>> I'd like to create a chunk of code that will handle all possible types
>> (for a particular operation) but how to do this isn't obvious.  I can
>> handle most common types, but there seem to be LOTS of less frequent types.
>
> You really should look at std.traits. It has that sort of stuff in it. It's
> what you should be using for really general stuff. Unqual, isDynamicArray,
> isFloatingPoint, etc. are all the sorts of things that you should be using for
> general tests on types.
>
> is(T == U) is going to be true if T and U are exactly the same type.
>
> is(T : U) is going to be true if T is implicitly convertible to U.
>
> If all that you care about is class or struct, then you can use
>
> is(T == class)
> is(T == struct)
>
> You should also look at http://www.d-programming-language.org/traits.html.
>
> - Jonathan M Davis

You're right.  std.traits is where I should be looking.
September 25, 2011
On 09/24/2011 04:31 PM, Jonathan M Davis wrote:
On 09/24/2011 04:31 PM, Jonathan M Davis wrote:
> On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
>> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
>>> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>>>> How would a specialize a parameterized class to only allow integral
>>>> parameters (i.e., anything that would respond "true" to
>>>> static if (is (T : long) )
>>>>
>>>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>>>> ucent) )", but those are still marked "reserved for future use".)
>>>>
>>>> I do want to allow byte, ubyte, etc. to be legal values.
>>>
>>> Parameterized? As in templated? Just use a template constraint.
>>>
>>> class C(T)
>>>
>>>       if(is(T : long))
>>>
>>> {
>>> }
>>>
>>> T will then be allowed to be anything which is implicitly convertible to
>>> long. I'd suggest using std.traits.isIntegral instead though.
>>>
>>> class C(T)
>>>
>>>       if(isIntegral!T)
>>>
>>> {
>>> }
>>>
>>> It specifically tests for whether the type is a byte, ubyte, short,
>>> ushort, int, uint, long, or ulong, so it won't included stray structs
>>> or classes which would be implicitly convertible to long, and if/when
>>> eont and ucent come along, they'd be added to isIntegral and be
>>> automatically supported.
>>>
>>> - Jonathan M Davis
>>
>> Thanks.  isIntegral has given me some error messages that I couldn't
>> understand, though, so I'll take your first suggestion.
>>
>> This is actually a rephrase of the question I first sent, when somehow
>> didn't appear on the list:
>>
>> When checking a template variable, what are the base cases for is?
>> long will satisfy all integer types.  I.e.
>>     is (typeof(tst0) : long)  == true
>> real will satisfy all floating point types.
>> I think that string will satisfy all arrays of characters (need to check
>> that).
>>
>> But there are lots of other kinds of array.  And while Object will
>> satisfy all classes, I don't know anything analogous for structs.  Then
>> there's enums (would they be caught by their base type as above, or with
>> they be like string and require an immutable corresponding to the base type?
>>
>> I'd like to create a chunk of code that will handle all possible types
>> (for a particular operation) but how to do this isn't obvious.  I can
>> handle most common types, but there seem to be LOTS of less frequent types.
>
> You really should look at std.traits. It has that sort of stuff in it. It's
> what you should be using for really general stuff. Unqual, isDynamicArray,
> isFloatingPoint, etc. are all the sorts of things that you should be using for
> general tests on types.
>
> is(T == U) is going to be true if T and U are exactly the same type.
>
> is(T : U) is going to be true if T is implicitly convertible to U.
>
> If all that you care about is class or struct, then you can use
>
> is(T == class)
> is(T == struct)
>
> You should also look at http://www.d-programming-language.org/traits.html.
>
> - Jonathan M Davis

> On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
>> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
>>> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>>>> How would a specialize a parameterized class to only allow integral
>>>> parameters (i.e., anything that would respond "true" to
>>>> static if (is (T : long) )
>>>>
>>>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>>>> ucent) )", but those are still marked "reserved for future use".)
>>>>
>>>> I do want to allow byte, ubyte, etc. to be legal values.
>>>
>>> Parameterized? As in templated? Just use a template constraint.
>>>
>>> class C(T)
>>>
>>>       if(is(T : long))
>>>
>>> {
>>> }
>>>
>>> T will then be allowed to be anything which is implicitly convertible to
>>> long. I'd suggest using std.traits.isIntegral instead though.
>>>
>>> class C(T)
>>>
>>>       if(isIntegral!T)
>>>
>>> {
>>> }
>>>
>>> It specifically tests for whether the type is a byte, ubyte, short,
>>> ushort, int, uint, long, or ulong, so it won't included stray structs
>>> or classes which would be implicitly convertible to long, and if/when
>>> eont and ucent come along, they'd be added to isIntegral and be
>>> automatically supported.
>>>
>>> - Jonathan M Davis
>>
>> Thanks.  isIntegral has given me some error messages that I couldn't
>> understand, though, so I'll take your first suggestion.
>>
>> This is actually a rephrase of the question I first sent, when somehow
>> didn't appear on the list:
>>
>> When checking a template variable, what are the base cases for is?
>> long will satisfy all integer types.  I.e.
>>     is (typeof(tst0) : long)  == true
>> real will satisfy all floating point types.
>> I think that string will satisfy all arrays of characters (need to check
>> that).
>>
>> But there are lots of other kinds of array.  And while Object will
>> satisfy all classes, I don't know anything analogous for structs.  Then
>> there's enums (would they be caught by their base type as above, or with
>> they be like string and require an immutable corresponding to the base type?
>>
>> I'd like to create a chunk of code that will handle all possible types
>> (for a particular operation) but how to do this isn't obvious.  I can
>> handle most common types, but there seem to be LOTS of less frequent types.
>
> You really should look at std.traits. It has that sort of stuff in it. It's
> what you should be using for really general stuff. Unqual, isDynamicArray,
> isFloatingPoint, etc. are all the sorts of things that you should be using for
> general tests on types.
>
> is(T == U) is going to be true if T and U are exactly the same type.
>
> is(T : U) is going to be true if T is implicitly convertible to U.
>
> If all that you care about is class or struct, then you can use
>
> is(T == class)
> is(T == struct)
>
> You should also look at http://www.d-programming-language.org/traits.html.
>
> - Jonathan M Davis

OK, here's the problem:
s$ dmd -unittest test2.d
/usr/include/d/dmd/phobos/std/traits.d(2576): Error: template std.traits.isNumeric(T) is not a function template
test2.d(8): Error: template std.traits.isNumeric(T) cannot deduce template function from argument types !()(int)
test2.d(192): Error: template instance Node!(int,string) does not match template declaration Node(Key,Data) if (isNumeric(Key))
test2.d(192): Error: Node!(int,string) is used as a type

The interesting thing is, that doesn't happen unless I compile with unittest.  I moved the offending statement:
	auto	tNode	=	new	Node!(int, string)(null);
into main, compiled without -unittest, and the thing compiled.  (I haven't tested it yet, so it might not work, but it's now looking that that's where the problem occurs.  So I *can* use isNumeric.

September 25, 2011
On Saturday, September 24, 2011 17:30:36 Charles Hixson wrote:
> OK, here's the problem:
> s$ dmd -unittest test2.d
> /usr/include/d/dmd/phobos/std/traits.d(2576): Error: template
> std.traits.isNumeric(T) is not a function template
> test2.d(8): Error: template std.traits.isNumeric(T) cannot deduce
> template function from argument types !()(int)
> test2.d(192): Error: template instance Node!(int,string) does not match
> template declaration Node(Key,Data) if (isNumeric(Key))
> test2.d(192): Error: Node!(int,string) is used as a type
> 
> The interesting thing is, that doesn't happen unless I compile with
> unittest.  I moved the offending statement:
> 	auto	tNode	=	new	Node!(int, string)(null);
> into main, compiled without -unittest, and the thing compiled.  (I
> haven't tested it yet, so it might not work, but it's now looking that
> that's where the problem occurs.  So I *can* use isNumeric.

I'm afraid that I'd need actual code to determine what the problem is. Without an example which shows the problem, I can't really figure out what's really happening.

- Jonathan M Davis
September 25, 2011
I spoke too soon.
class	AA(Key, Data)	if	(isNumeric (Key) )
 didn't work with a larger case,

s$ dmd aa.d
/usr/include/d/dmd/phobos/std/traits.d(2576): Error: template std.traits.isNumeric(T) is not a function template
aa.d(200): Error: template std.traits.isNumeric(T) cannot deduce template function from argument types !()(int)
aa.d(494): Error: template instance AA!(int,string) does not match template declaration AA(Key,Data) if (isNumeric(Key))
aa.d(494): Error: AA!(int,string) is used as a type


though
class	AA (Key, Data)	if (is (Key : long))
did work.  Or at least it compiled without error.

On 09/24/2011 05:05 PM, Charles Hixson wrote:
On 09/24/2011 05:05 PM, Charles Hixson wrote:
> On 09/24/2011 04:31 PM, Jonathan M Davis wrote:
>> On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
>>> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
>>>> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>>>>> How would a specialize a parameterized class to only allow integral
>>>>> parameters (i.e., anything that would respond "true" to
>>>>> static if (is (T : long) )
>>>>>
>>>>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>>>>> ucent) )", but those are still marked "reserved for future use".)
>>>>>
>>>>> I do want to allow byte, ubyte, etc. to be legal values.
>>>>
>>>> Parameterized? As in templated? Just use a template constraint.
>>>>
>>>> class C(T)
>>>>
>>>> if(is(T : long))
>>>>
>>>> {
>>>> }
>>>>
>>>> T will then be allowed to be anything which is implicitly
>>>> convertible to
>>>> long. I'd suggest using std.traits.isIntegral instead though.
>>>>
>>>> class C(T)
>>>>
>>>> if(isIntegral!T)
>>>>
>>>> {
>>>> }
>>>>
>>>> It specifically tests for whether the type is a byte, ubyte, short,
>>>> ushort, int, uint, long, or ulong, so it won't included stray structs
>>>> or classes which would be implicitly convertible to long, and if/when
>>>> eont and ucent come along, they'd be added to isIntegral and be
>>>> automatically supported.
>>>>
>>>> - Jonathan M Davis
>>>
>>> Thanks. isIntegral has given me some error messages that I couldn't
>>> understand, though, so I'll take your first suggestion.
>>>
>>> This is actually a rephrase of the question I first sent, when somehow
>>> didn't appear on the list:
>>>
>>> When checking a template variable, what are the base cases for is?
>>> long will satisfy all integer types. I.e.
>>> is (typeof(tst0) : long) == true
>>> real will satisfy all floating point types.
>>> I think that string will satisfy all arrays of characters (need to check
>>> that).
>>>
>>> But there are lots of other kinds of array. And while Object will
>>> satisfy all classes, I don't know anything analogous for structs. Then
>>> there's enums (would they be caught by their base type as above, or with
>>> they be like string and require an immutable corresponding to the
>>> base type?
>>>
>>> I'd like to create a chunk of code that will handle all possible types
>>> (for a particular operation) but how to do this isn't obvious. I can
>>> handle most common types, but there seem to be LOTS of less frequent
>>> types.
>>
>> You really should look at std.traits. It has that sort of stuff in it.
>> It's
>> what you should be using for really general stuff. Unqual,
>> isDynamicArray,
>> isFloatingPoint, etc. are all the sorts of things that you should be
>> using for
>> general tests on types.
>>
>> is(T == U) is going to be true if T and U are exactly the same type.
>>
>> is(T : U) is going to be true if T is implicitly convertible to U.
>>
>> If all that you care about is class or struct, then you can use
>>
>> is(T == class)
>> is(T == struct)
>>
>> You should also look at
>> http://www.d-programming-language.org/traits.html.
>>
>> - Jonathan M Davis
>
> You're right. std.traits is where I should be looking.

> On 09/24/2011 04:31 PM, Jonathan M Davis wrote:
>> On Saturday, September 24, 2011 16:14:48 Charles Hixson wrote:
>>> On 09/24/2011 02:33 PM, Jonathan M Davis wrote:
>>>> On Saturday, September 24, 2011 14:16:12 Charles Hixson wrote:
>>>>> How would a specialize a parameterized class to only allow integral
>>>>> parameters (i.e., anything that would respond "true" to
>>>>> static if (is (T : long) )
>>>>>
>>>>> (I'd have said "static if (is (T : cent) )" or "static if (is (T :
>>>>> ucent) )", but those are still marked "reserved for future use".)
>>>>>
>>>>> I do want to allow byte, ubyte, etc. to be legal values.
>>>>
>>>> Parameterized? As in templated? Just use a template constraint.
>>>>
>>>> class C(T)
>>>>
>>>> if(is(T : long))
>>>>
>>>> {
>>>> }
>>>>
>>>> T will then be allowed to be anything which is implicitly
>>>> convertible to
>>>> long. I'd suggest using std.traits.isIntegral instead though.
>>>>
>>>> class C(T)
>>>>
>>>> if(isIntegral!T)
>>>>
>>>> {
>>>> }
>>>>
>>>> It specifically tests for whether the type is a byte, ubyte, short,
>>>> ushort, int, uint, long, or ulong, so it won't included stray structs
>>>> or classes which would be implicitly convertible to long, and if/when
>>>> eont and ucent come along, they'd be added to isIntegral and be
>>>> automatically supported.
>>>>
>>>> - Jonathan M Davis
>>>
>>> Thanks. isIntegral has given me some error messages that I couldn't
>>> understand, though, so I'll take your first suggestion.
>>>
>>> This is actually a rephrase of the question I first sent, when somehow
>>> didn't appear on the list:
>>>
>>> When checking a template variable, what are the base cases for is?
>>> long will satisfy all integer types. I.e.
>>> is (typeof(tst0) : long) == true
>>> real will satisfy all floating point types.
>>> I think that string will satisfy all arrays of characters (need to check
>>> that).
>>>
>>> But there are lots of other kinds of array. And while Object will
>>> satisfy all classes, I don't know anything analogous for structs. Then
>>> there's enums (would they be caught by their base type as above, or with
>>> they be like string and require an immutable corresponding to the
>>> base type?
>>>
>>> I'd like to create a chunk of code that will handle all possible types
>>> (for a particular operation) but how to do this isn't obvious. I can
>>> handle most common types, but there seem to be LOTS of less frequent
>>> types.
>>
>> You really should look at std.traits. It has that sort of stuff in it.
>> It's
>> what you should be using for really general stuff. Unqual,
>> isDynamicArray,
>> isFloatingPoint, etc. are all the sorts of things that you should be
>> using for
>> general tests on types.
>>
>> is(T == U) is going to be true if T and U are exactly the same type.
>>
>> is(T : U) is going to be true if T is implicitly convertible to U.
>>
>> If all that you care about is class or struct, then you can use
>>
>> is(T == class)
>> is(T == struct)
>>
>> You should also look at
>> http://www.d-programming-language.org/traits.html.
>>
>> - Jonathan M Davis
>
> You're right. std.traits is where I should be looking.

September 25, 2011
On Saturday, September 24, 2011 17:41:52 Charles Hixson wrote:
> I spoke too soon.
> class	AA(Key, Data)	if	(isNumeric (Key) )
>   didn't work with a larger case,

isNumeric!Key

std.straits.isNumeric is an eponymous template, _not_ a function. I believe that everything in std.traits is an eponymous template, and pretty much anything that takes a type is going to be a template, and not a function. Look at the examples in std.traits, and you'll notice that they all use !.

But essentially, it sounds like what you've been trying to do is failing, because you're treating the eponymous templates in std.traits as if they were functions.

- Jonathan M Davis
September 25, 2011
On 09/24/2011 05:49 PM, Jonathan M Davis wrote:
> On Saturday, September 24, 2011 17:41:52 Charles Hixson wrote:
>> I spoke too soon.
>> class	AA(Key, Data)	if	(isNumeric (Key) )
>>    didn't work with a larger case,
>
> isNumeric!Key
>
> std.straits.isNumeric is an eponymous template, _not_ a function. I believe
> that everything in std.traits is an eponymous template, and pretty much
> anything that takes a type is going to be a template, and not a function. Look
> at the examples in std.traits, and you'll notice that they all use !.
>
> But essentially, it sounds like what you've been trying to do is failing,
> because you're treating the eponymous templates in std.traits as if they were
> functions.
>
> - Jonathan M Davis

Thank you.  That was, indeed, my problem.