www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - String and opBinary

reply "Eyyub" <eyyub.pangearaion gmail.com> writes:
Hi,

I'd like to know why this following code doesn't compile :

string opBinary(string op : "*")(string data, string word)
{
	string temp;
	foreach(letter; word)
	{
		temp ~= data;
	}
	return temp;
}

void main()
{
	string word = "foo";
	string secretword = "_" * word; //Error: '"_"' is not of 
arithmetic type                            it is a string
         //Error: 'word' is not of arithmetic type, it is a string
	string secretword = "_".opBinary!"*"(word); // compile
	writeln(secretword); // output : ___
}

Even more weird, with just another op specialisation but the same 
function's body :
string opBinary(string op : "+")(string data, string word)
{
	string temp;
	foreach(letter; word)
	{
		temp ~= data;
	}
	return temp;
}

void main()
{
	string word = "foo";
	string secretword = "_" + word; // Error: Array operation "_" - 
word not implemented // why the error message is not the same 
with different op ?
	string secretword = "_".opBinary!"+"(word); // this works fine
}

Thanks,

(sorry for my bad english)
Jun 01 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 01, 2012 19:51:35 Eyyub wrote:
 Hi,
 
 I'd like to know why this following code doesn't compile :
 
 string opBinary(string op : "*")(string data, string word)
 {
 string temp;
 foreach(letter; word)
 {
 temp ~= data;
 }
 return temp;
 }
 
 void main()
 {
 string word = "foo";
 string secretword = "_" * word; //Error: '"_"' is not of
 arithmetic type it is a string
 //Error: 'word' is not of arithmetic type, it is a string
 string secretword = "_".opBinary!"*"(word); // compile
 writeln(secretword); // output : ___
 }
 
 Even more weird, with just another op specialisation but the same
 function's body :
 string opBinary(string op : "+")(string data, string word)
 {
 string temp;
 foreach(letter; word)
 {
 temp ~= data;
 }
 return temp;
 }
 
 void main()
 {
 string word = "foo";
 string secretword = "_" + word; // Error: Array operation "_" -
 word not implemented // why the error message is not the same
 with different op ?
 string secretword = "_".opBinary!"+"(word); // this works fine
 }
 
 Thanks,
 
 (sorry for my bad english)

I don't believe that it's legal to declare overloaded operators for built-in types. So, it's not legal to do what you're trying to do. You can call the function directly, because it's a valid function, but it isn't used to overload any operators. As for why you're getting a complaint about subtraction in the second example, I don't know. Running the current, development version from github I get a +, so it may be a bug in whatever version of the compiler that you're using that has since been fixed. - Jonathan M Davis
Jun 01 2012
prev sibling next sibling parent reply "Zhenya" <zheny list.ru> writes:
On Friday, 1 June 2012 at 17:51:36 UTC, Eyyub wrote:
 Hi,

 I'd like to know why this following code doesn't compile :

 string opBinary(string op : "*")(string data, string word)
 {
 	string temp;
 	foreach(letter; word)
 	{
 		temp ~= data;
 	}
 	return temp;
 }

 void main()
 {
 	string word = "foo";
 	string secretword = "_" * word; //Error: '"_"' is not of 
 arithmetic type                            it is a string
         //Error: 'word' is not of arithmetic type, it is a 
 string
 	string secretword = "_".opBinary!"*"(word); // compile
 	writeln(secretword); // output : ___
 }

 Even more weird, with just another op specialisation but the 
 same function's body :
 string opBinary(string op : "+")(string data, string word)
 {
 	string temp;
 	foreach(letter; word)
 	{
 		temp ~= data;
 	}
 	return temp;
 }

 void main()
 {
 	string word = "foo";
 	string secretword = "_" + word; // Error: Array operation "_" 
 - word not implemented // why the error message is not the same 
 with different op ?
 	string secretword = "_".opBinary!"+"(word); // this works fine
 }

 Thanks,

 (sorry for my bad english)

//Operator overloading is accomplished by rewriting operators whose operands //are class or struct objects into calls to specially named member functions I'm not sure,but problem may be that opBinary should be member function
Jun 01 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 01.06.2012 23:37, Zhenya wrote:
 This code work

 import std.stdio;

 struct String
 {
 string data;
 alias data this;
 this(string s)
 {
 data = s;
 }
 String opBinary(string op : "*")(string word)
 {
 string temp;
 foreach(letter; word)
 {
 temp ~= data;
 }
 return String(temp);
 }
 };

 string opBinary(string op : "*")(string data, string word)
 {
 string temp;
 foreach(letter; word)
 {
 temp ~= data;
 }
 return temp;
 }

 void main()
 {
 String word = "foo";
 String secretword = String("_") * word;

Define proper opBinaryRight and this will work too: String secretword = "_" * word;
 //string secretword = "_".opBinary!"*"(word); // compile
 writeln(secretword); // output : ___
 }

-- Dmitry Olshansky
Jun 01 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Eyyub:

 I'd like to know why this following code doesn't compile :

 string opBinary(string op : "*")(string data, string word)
 {
 	string temp;
 	foreach(letter; word)
 	{
 		temp ~= data;
 	}
 	return temp;
 }

In D to work an overloaded operator like that needs to be a class/struct method. Bye, bearophile
Jun 01 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
This code work

import std.stdio;

struct String
{
	string data;
	alias data this;
	this(string s)
	{
		data = s;
	}
	String opBinary(string op : "*")(string word)
	{
		string temp;
		foreach(letter; word)
		{
			temp ~= data;
		}
		return String(temp);
	}
};

string opBinary(string op : "*")(string data, string word)
{
	string temp;
	foreach(letter; word)
	{
		temp ~= data;
	}
	return temp;
}

void main()
{
	String word = "foo";
	String secretword = String("_") * word;
  	//string secretword = "_".opBinary!"*"(word); // compile
	writeln(secretword); // output : ___
}
Jun 01 2012
prev sibling next sibling parent "Eyyub" <eyyub.pangearaion gmail.com> writes:
On Friday, 1 June 2012 at 19:37:38 UTC, Zhenya wrote:
 This code work

 import std.stdio;

 struct String
 {
 	string data;
 	alias data this;
 	this(string s)
 	{
 		data = s;
 	}
 	String opBinary(string op : "*")(string word)
 	{
 		string temp;
 		foreach(letter; word)
 		{
 			temp ~= data;
 		}
 		return String(temp);
 	}
 };

 string opBinary(string op : "*")(string data, string word)
 {
 	string temp;
 	foreach(letter; word)
 	{
 		temp ~= data;
 	}
 	return temp;
 }

 void main()
 {
 	String word = "foo";
 	String secretword = String("_") * word;
  	//string secretword = "_".opBinary!"*"(word); // compile
 	writeln(secretword); // output : ___
 }

Hi Zhenya, thanks for your reply ! I considered using this tip but that doesn't look nice compared to the C++ way does it. :/ Why doesn't D allow a way to write operator overloading at scope-module level like in C++ ?(in this case) (Thanks for your tip Dmitry)
Jun 01 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 01, 2012 22:18:50 Eyyub wrote:
 Why doesn't D allow a way to write operator overloading at
 scope-module level like in C++ ?(in this case)

Why would you need to? It only works when defining them for user-defined types anyway. So, having them be member functions makes perfect sense. And opBinaryRight solves the problem of needing the overload where the other type is on the left rather than the one that you're defining the overloaded operator for, which is the typical reason to define an overloaded operator as a friend function rather than a member function in C++. - Jonathan M Davis
Jun 01 2012
prev sibling parent "Eyyub" <eyyub.pangearaion gmail.com> writes:
On Friday, 1 June 2012 at 21:26:55 UTC, Jonathan M Davis wrote:
 On Friday, June 01, 2012 22:18:50 Eyyub wrote:
 Why doesn't D allow a way to write operator overloading at
 scope-module level like in C++ ?(in this case)

Why would you need to? It only works when defining them for user-defined types anyway. So, having them be member functions makes perfect sense. And opBinaryRight solves the problem of needing the overload where the other type is on the left rather than the one that you're defining the overloaded operator for, which is the typical reason to define an overloaded operator as a friend function rather than a member function in C++. - Jonathan M Davis

Hi, I asked this question just for know if there are a reason about this choice. Anyway, want to multiply a string by a string is a non-sense. :P Thanks,
Jun 01 2012