Thread overview
building char[][] in templates
Dec 17, 2006
BCS
Dec 18, 2006
Kevin Bealer
Dec 18, 2006
Bill Baxter
Dec 18, 2006
BCS
December 17, 2006
I'm about ready to pull my hair out!!!
I'm trying to write a template that will split a string based on a character:

> char[][] foo = SplitString!("hello|world|this|is|a|test",'|'); // foo == ["hello","world","this","is","a","test"];

I keep getting an error about this being non-const:

> null[0..0] ~ "hello" ~ "world" ~ "this" ~ "is" ~ "a" ~ "test"

I'm doing something like this:

>template SplitString(char[] string, char c)
>{
>	static if(string == "")
>		char[][] SplitString = (char[][]).init;
>	else
>		char[][] SplitString = SplitString!(BeforLast!(string,c),c) ~ AfterLast!(string,c);
>}

Any ideas??



Better yet would be a template that evaluates to a tuple

>template SplitString(char[] string, char c, V...)
>{
>	static if(string == "")
>		auto SplitString = V;
>	else
>		auto SplitString = SplitString!(BeforLast!(string,c),c, V, AfterLast!(string,c));
>}

that would allow this:

>void foo(char[] string)
>{
>	// static foreach
>	foreach(s;SplitString!("hello|world|this|is|a|test",'|'))
>	{
>		//use s as const
>	}
>}

December 18, 2006
I've never done this myself, but there is an example of a metaprogramming regex parser at the bottom of this page:

http://www.digitalmars.com/d/templates-revisited.html

Kevin
December 18, 2006
Kevin Bealer wrote:
> I've never done this myself, but there is an example of a metaprogramming regex
> parser at the bottom of this page:
> 
> http://www.digitalmars.com/d/templates-revisited.html
> 
> Kevin

If actually splitting the string doesn't work then maybe you can manage to have it generate a tuple of ints that represent the split points.


--bb
December 18, 2006
Bill Baxter wrote:
> Kevin Bealer wrote:
> 
>> I've never done this myself, but there is an example of a metaprogramming regex
>> parser at the bottom of this page:
>>
>> http://www.digitalmars.com/d/templates-revisited.html
>>
>> Kevin
> 
> 
> If actually splitting the string doesn't work then maybe you can manage to have it generate a tuple of ints that represent the split points.
> 
> 
> --bb

This is what I ended up using (and it actually does a better job for what I was trying to do) it returns a tuple.

/************
	Return a slice up-to but not including the first instance of t.
*/
template UseTill(char[] string, char t)
{
	static if(string == "" || string[0] == t)
		const char[] UseTill = "";
	else
		const char[] UseTill = string[0..1] ~ UseTill!(string[1..$],t);
}

/***********
	Return a slice starting after the first instance of t and containing the rest of the string.
*/
template DiscardTill(char[] string, char t)
{
	static if(string == "")
		const char[] DiscardTill = "";
	else static if(string[0] == t)
		const char[] DiscardTill = string[1..$];
	else
		const char[] DiscardTill = DiscardTill!(string[1..$],t);
}

/***********
	mixin temp with {V + 'string' broken up by 'c'}
*/
template BreakBy(char[] string, char d, V...)
{
	static if(string == "")
		alias V BreakBy;
	else static
		alias BreakBy!(DiscardTill!(string,d), d, V, UseTill!(string,d)) BreakBy;
}