class specialization for integral types

Charles Hixson charleshixsn at earthlink.net
Sat Sep 24 17:30:36 PDT 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.



More information about the Digitalmars-d-learn mailing list