Jump to page: 1 2
Thread overview
Template function that accept strings and array of strings
Jul 15, 2015
badlink
Jul 15, 2015
Vlad Levenfeld
Jul 15, 2015
Yuxuan Shui
Jul 16, 2015
Jacob Carlborg
Jul 16, 2015
badlink
Jul 17, 2015
Jacob Carlborg
Jul 17, 2015
badlink
Jul 17, 2015
Jacob Carlborg
Jul 16, 2015
Gary Willoughby
Jul 16, 2015
Gary Willoughby
Jul 16, 2015
badlink
Jul 16, 2015
badlink
July 15, 2015
Hello, I can't figure how to write a template function that accept either strings or array of strings.

This is my current code:

bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
if (is(typeof(T) == char) || (isArray!T && is(typeof(T[]) == char)))
{...}

I used const(T)[] because I'd like to accept immutable and mutable strings.
But calling it with an immutable string generate this error:

Error: template cache.MetadataCache.hasItemParent cannot deduce function from argument types !()(string, string), candidates are:
cache.MetadataCache.hasItemParent(T)(const(char)[] itemId, const(T)[] parentId) if (is(typeof(T) == char))

Any suggestions ?
July 15, 2015
On Wednesday, 15 July 2015 at 21:57:50 UTC, badlink wrote:
> Hello, I can't figure how to write a template function that accept either strings or array of strings.
>
> This is my current code:
>
> bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
> if (is(typeof(T) == char) || (isArray!T && is(typeof(T[]) == char)))
> {...}
>
> I used const(T)[] because I'd like to accept immutable and mutable strings.
> But calling it with an immutable string generate this error:
>
> Error: template cache.MetadataCache.hasItemParent cannot deduce function from argument types !()(string, string), candidates are:
> cache.MetadataCache.hasItemParent(T)(const(char)[] itemId, const(T)[] parentId) if (is(typeof(T) == char))
>
> Any suggestions ?

T is already a type, so typeof(T) is an error, which makes the constraint fail.

Try
hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
if (is(T == char) || is (T == char[]))

at least I think that's what you meant. typeof(anything[]) will never == char.
July 15, 2015
On Wednesday, 15 July 2015 at 21:57:50 UTC, badlink wrote:
> Hello, I can't figure how to write a template function that accept either strings or array of strings.
>
> This is my current code:
>
> bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
> if (is(typeof(T) == char) || (isArray!T && is(typeof(T[]) == char)))
> {...}
>
> I used const(T)[] because I'd like to accept immutable and mutable strings.
> But calling it with an immutable string generate this error:
>
> Error: template cache.MetadataCache.hasItemParent cannot deduce function from argument types !()(string, string), candidates are:
> cache.MetadataCache.hasItemParent(T)(const(char)[] itemId, const(T)[] parentId) if (is(typeof(T) == char))
>
> Any suggestions ?

T is already a type, you don't need to typeof() it.

This should work:

bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
if (is(T == char) || (isArray!T && is(ElementType!T == char)))

July 16, 2015
On 2015-07-15 23:57, badlink wrote:
> Hello, I can't figure how to write a template function that accept
> either strings or array of strings.
>
> This is my current code:
>
> bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
> if (is(typeof(T) == char) || (isArray!T && is(typeof(T[]) == char)))
> {...}
>
> I used const(T)[] because I'd like to accept immutable and mutable strings.
> But calling it with an immutable string generate this error:
>
> Error: template cache.MetadataCache.hasItemParent cannot deduce function
> from argument types !()(string, string), candidates are:
> cache.MetadataCache.hasItemParent(T)(const(char)[] itemId, const(T)[]
> parentId) if (is(typeof(T) == char))
>
> Any suggestions ?

If I understand you correctly, I think you want a type safe variadic function:

void foo (const(char[])[] args ...)
{
    writeln(args);
}

void main()
{
    foo("foo", "bar");
    foo("foo".dup, "bar".dup);
    auto a = ["foo", "bar"];
    foo(a);
    auto b = ["foo".dup, "bar".dup];
    foo(b);
}

-- 
/Jacob Carlborg
July 16, 2015
Thank you for all answers.

Removing typeof do resolve the problem when the second parameter is a simple string.
However when passing an array of string the error still occur:
Error: template cache.MetadataCache.hasItemParent cannot deduce function from argument types !()(string, string[]).

The method with the variadic function works, but I would have to use only one parameter because this doesn't work:
fun(const(char[])[] a, const(char[])[] b ...)
and is a bit ugly in my use case ...

After some tests I found that:
if (is(T == char) || is(T == string))
works, so I assume the problem is the immutable nature of string that breaks the type checking.

What should I use to enable this function to accept all combinations char[], const(char)[], and immutable(char) ?


July 16, 2015
On Wednesday, 15 July 2015 at 21:57:50 UTC, badlink wrote:
> Hello, I can't figure how to write a template function that accept either strings or array of strings.
>
> This is my current code:
>
> bool hasItemParent(T)(const(char)[] itemId, const(T)[] parentId)
> if (is(typeof(T) == char) || (isArray!T && is(typeof(T[]) == char)))
> {...}
>
> I used const(T)[] because I'd like to accept immutable and mutable strings.
> But calling it with an immutable string generate this error:
>
> Error: template cache.MetadataCache.hasItemParent cannot deduce function from argument types !()(string, string), candidates are:
> cache.MetadataCache.hasItemParent(T)(const(char)[] itemId, const(T)[] parentId) if (is(typeof(T) == char))
>
> Any suggestions ?

Something like this:


import std.stdio;
import std.traits;
import std.range;

bool hasItemParent(A, B)(A itemId, B parentId)
if (isSomeString!(A) && (isSomeString!(B) || isArray!(B) && isSomeString!(ElementType!(B))))
{
	writefln("%s", typeof(parentId).stringof);
	return true;
}

void main(string[] args)
{

	string one             = "foo";
	char[] two             = "foo".dup;
	const(char)[] three    = "foo";
	immutable(char)[] four = "foo";

	string[] five             = ["foo", "bar"];
	char[][] six              = ["foo".dup, "bar".dup];
	const(char)[][] seven     = ["foo", "bar"];
	immutable(char)[][] eight = ["foo", "bar"];

	hasItemParent(one, one);
	hasItemParent(two, two);
	hasItemParent(three, three);
	hasItemParent(four, four);

	hasItemParent(one, five);
	hasItemParent(two, six);
	hasItemParent(three, seven);
	hasItemParent(four, eight);
}

July 16, 2015
Also checkout inout functions:

http://dlang.org/function.html#inout-functions
July 16, 2015
On Thursday, 16 July 2015 at 18:41:47 UTC, Gary Willoughby wrote:
> bool hasItemParent(A, B)(A itemId, B parentId)
> if (isSomeString!(A) && (isSomeString!(B) || isArray!(B) && isSomeString!(ElementType!(B))))

Thank you ! I completely missed isSomeString.

I think the definition can be safely shortened to:
bool hasItemParent(T)(const(char)[] itemId, T parentId)
if (isSomeString!T || isSomeString!(ElementType!T))

Minor flaw, as it is the function also accepts wchar[] and dchar[] that break the compilation because I do comparisons with char[].
July 16, 2015
After a thorough reading of the documentation I found an even simpler solution:

bool hasItemParent(T)(const(char)[] itemId, T parentId)
if (is(T : const(char)[]) || is(T : const(char[])[]))
{ ... }

Now it accepts all these: char[], const(char)[], immutable(char)[], char[][], const(char)[][] ,immutable(char)[][] but not their wchar and dchar counterparts.

July 17, 2015
On 2015-07-16 18:49, badlink wrote:

> The method with the variadic function works, but I would have to use
> only one parameter because this doesn't work:
> fun(const(char[])[] a, const(char[])[] b ...)
> and is a bit ugly in my use case ...

I don't think I really understand how you want to use/call the function. Could you give an example with all the different types you want to call the function?

-- 
/Jacob Carlborg
« First   ‹ Prev
1 2