Thread overview
Check template parameter whether it has "length"
Oct 08, 2015
tcak
Oct 08, 2015
John Colvin
Oct 08, 2015
tcak
Oct 08, 2015
John Colvin
Oct 08, 2015
Meta
Oct 08, 2015
Artur Skawina
Oct 08, 2015
Nicholas Wilson
October 08, 2015
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
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
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
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
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
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
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