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