Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
October 08, 2015 Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
I am "trying" to write a function that takes an array of items, and returns the length of longest item. [code] size_t maxLength(A)( const A[] listOfString ) if( __traits( hasMember, A, "length" ) ) { return 0; // not implemented yet } [/code] I tried it with if( __traits( compiles, A.length ) ) as well. But compiler doesn't match it. writeln("Max Length: ", maxLength( ["foo", "123456789"] )); Compilers says it cannot deduce function from argument types ... I do not want to check whether the type "A" is string, char[], etc. As long as it has length (please do not put me into ranges, library functions etc as much as possible), I want the function to accept it. |
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to tcak | On Thursday, 8 October 2015 at 09:29:30 UTC, tcak wrote:
> I am "trying" to write a function that takes an array of items, and returns the length of longest item.
>
> [code]
> size_t maxLength(A)( const A[] listOfString ) if( __traits( hasMember, A, "length" ) )
> {
> return 0; // not implemented yet
> }
> [/code]
>
> I tried it with
>
> if( __traits( compiles, A.length ) )
>
> as well. But compiler doesn't match it.
>
> writeln("Max Length: ", maxLength( ["foo", "123456789"] ));
>
> Compilers says it cannot deduce function from argument types ...
>
> I do not want to check whether the type "A" is string, char[], etc. As long as it has length (please do not put me into ranges, library functions etc as much as possible), I want the function to accept it.
I'm 99% sure something like __traits(hasMember, int[], "length" ) should evaluate to true. Please file a bug at issues.dlang.org I notice it also doesn't work for "ptr".
The correct workaround:
__traits(compiles, A.init.length ));
or
__traits(compiles, listOfStrings.length ));
A.length doesn't work because length is not a static member, so it's only accessible from an instance.
The __traits(compiles, ...) solution is actually more general because it will work if .length is implemented via UFCS and opDispatch.
FYI:
If you want to check whether a statement will compile, as opposed to an expression, make a function/delegate out of it, e.g.:
__traits(compiles, { size_t n = A.init.length; });
to check that A has a member length that can be assigned to size_t.
P.S. always check std.traits for solutions all your static reflection problems, there's a lot of good stuff in there.
|
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to tcak | On 10/08/15 11:29, tcak via Digitalmars-d-learn wrote: > I am "trying" to write a function that takes an array of items, and returns the length of longest item. > > [code] > size_t maxLength(A)( const A[] listOfString ) if( __traits( hasMember, A, "length" ) ) > { > return 0; // not implemented yet > } > [/code] > > I tried it with > > if( __traits( compiles, A.length ) ) > > as well. But compiler doesn't match it. Use `A.init.length` instead of `A.length`. You could also use something like if(is(typeof(A.init.length):size_t)) artur |
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to tcak | On Thursday, 8 October 2015 at 09:29:30 UTC, tcak wrote:
> I am "trying" to write a function that takes an array of items, and returns the length of longest item.
>
> [code]
> size_t maxLength(A)( const A[] listOfString ) if( __traits( hasMember, A, "length" ) )
> {
> return 0; // not implemented yet
> }
> [/code]
>
> I tried it with
>
> if( __traits( compiles, A.length ) )
>
> as well. But compiler doesn't match it.
>
> writeln("Max Length: ", maxLength( ["foo", "123456789"] ));
>
> Compilers says it cannot deduce function from argument types ...
>
> I do not want to check whether the type "A" is string, char[], etc. As long as it has length (please do not put me into ranges, library functions etc as much as possible), I want the function to accept it.
iirc there's a hasLength trait in std.traits e.g. static assert(hasLength!int[])
|
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Thursday, 8 October 2015 at 09:50:12 UTC, John Colvin wrote:
> On Thursday, 8 October 2015 at 09:29:30 UTC, tcak wrote:
>> [...]
>
> I'm 99% sure something like __traits(hasMember, int[], "length" ) should evaluate to true. Please file a bug at issues.dlang.org I notice it also doesn't work for "ptr".
>
> The correct workaround:
> __traits(compiles, A.init.length ));
> or
> __traits(compiles, listOfStrings.length ));
>
> A.length doesn't work because length is not a static member, so it's only accessible from an instance.
>
> The __traits(compiles, ...) solution is actually more general because it will work if .length is implemented via UFCS and opDispatch.
>
> FYI:
> If you want to check whether a statement will compile, as opposed to an expression, make a function/delegate out of it, e.g.:
> __traits(compiles, { size_t n = A.init.length; });
> to check that A has a member length that can be assigned to size_t.
>
> P.S. always check std.traits for solutions all your static reflection problems, there's a lot of good stuff in there.
__traits(compiles, { size_t n = A.init.length; }); did the trick.
[code]
size_t maxLength(A)( const A[] listOfString )
if( __traits( compiles, { size_t len = A.init.length; } ) )
{
size_t len = 0;
foreach(A str; listOfString)
if( str.length > len ) len = str.length;
return len;
}
[/code]
BTW, there is nothing like std.traits.hasLength.
|
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to tcak | On Thursday, 8 October 2015 at 15:22:02 UTC, tcak wrote:
> BTW, there is nothing like std.traits.hasLength.
yeah, that's because __traits(hasMember, ...) should be good enough, but obviously not in this case at the moment.
|
October 08, 2015 Re: Check template parameter whether it has "length" | ||||
---|---|---|---|---|
| ||||
Posted in reply to tcak | On Thursday, 8 October 2015 at 15:22:02 UTC, tcak wrote: > BTW, there is nothing like std.traits.hasLength. You're just looking in the wrong place =) http://dlang.org/phobos/std_range_primitives.html#hasLength |
Copyright © 1999-2021 by the D Language Foundation