January 30, 2019
On 1/30/2019 1:28 PM, H. S. Teoh wrote:
> Recent versions of C++ ostensibly have "solved" that problem, so that no
> intervening space is needed anymore.

I implemented the lexer hack back in the 90's, but had to back it out to get it through the C++98 test suite. Then, I had to add it back in to match later C++ Standards :-)


> Of course, that doesn't really solve the problem; it only introduces
> more complexity in the parser / lexer, and in all likelihood more
> pathological corner cases to come back and bite you when you least
> expect it.

I think the .template syntax is to work around such a corner case.
January 30, 2019
On Wed, Jan 30, 2019 at 01:28:39PM -0800, H. S. Teoh via Digitalmars-d wrote: [...]
> 	myFunc<T, U>(a, b);
[...]

OK, so I decided to amuse myself a little today, and worked out the fully-compilable C++ code that showcases exactly the above line doing something completely different from what you might think it does.

First, take a look at main() at the bottom, especially the last two lines. Now see if you can figure out what they do.  Compile and run it yourself to find out what it actually does. :-D  Now imagine if you inherited this code from an ex-employee and are now responsible for maintaining it.  Good luck!

-----------------------------------snip------------------------------------
// Totally evil example of why C++ template syntax and free-for-all operator
// overloading is a Bad, Bad Idea.
#include <iostream>

struct Bad { };

struct B { };

struct A {
	Bad operator,(B b) { return Bad(); }
};

struct D { };

struct Ugly {
	D operator>(Bad b) { return D(); }
} U;

struct Terrible { } T;

struct Evil {
	~Evil() {
		std::cout << "Hard drive reformatted." << std::endl;
	}
};

struct Nasty {
	Evil operator,(D d) { return Evil(); }
};

struct Idea {
	void operator()(A a, B b) {
		std::cout << "Good idea, data saved." << std::endl;
	}
	Nasty operator<(Terrible t) { return Nasty(); }
} gun;

template<typename T, typename U>
void fun(A a, B b) {
	std::cout << "Have fun!" << std::endl;
}

int main() {
	A a;
	B b;

	// What do these lines do?
	fun<A, B>(a, b);
	gun<T, U>(a, b);
}
-----------------------------------snip------------------------------------


T

-- 
To provoke is to call someone stupid; to argue is to call each other stupid.
January 30, 2019
On Wed, Jan 30, 2019 at 01:54:47PM -0800, Walter Bright via Digitalmars-d wrote:
> On 1/30/2019 12:12 PM, H. S. Teoh wrote:
> > Please, let's leave C++'s < > mistake in the dustbins of history. Such suffering ought not be inflicted upon our future generations.
> 
> To pile it on, C++ iostreams overloads << and >> operators.

Sigh, you made me do it. Couldn't resist:

	#include <iostream>

	struct Sigh { };
	struct You {
		Sigh operator>>(std::string s) { return Sigh(); }
	} U;
	struct Me { };
	struct Do {
		Me operator<(Sigh m) { return Me(); }
	} traits;
	struct It { } T;

	struct Couldnt {
		void operator,(Me i) {
			std::cout << "Goodbye, earth" << std::endl;
		}
	};
	struct Resist {
		void operator()(std::string msg) {
			std::cout << msg << std::endl;
		}
		Couldnt operator<(It t) { return Couldnt(); }
	} fun;

	int main() {
		// What does this line do?
		fun<T, traits<U>>("Hello world");
	}

:-D


T

-- 
Never trust an operating system you don't have source for! -- Martin Schulze
January 30, 2019
On 1/30/19 4:57 PM, Walter Bright wrote:
> On 1/30/2019 1:28 PM, H. S. Teoh wrote:
>> Recent versions of C++ ostensibly have "solved" that problem, so that no
>> intervening space is needed anymore.
> 
> I implemented the lexer hack back in the 90's, but had to back it out to get it through the C++98 test suite. Then, I had to add it back in to match later C++ Standards :-)
> 
> 
>> Of course, that doesn't really solve the problem; it only introduces
>> more complexity in the parser / lexer, and in all likelihood more
>> pathological corner cases to come back and bite you when you least
>> expect it.
> 
> I think the .template syntax is to work around such a corner case.

Don't forget "typename" and "::template", beautifully combined here:

typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;


Andrei

January 30, 2019
On 1/30/2019 4:08 PM, Andrei Alexandrescu wrote:
> Don't forget "typename" and "::template", beautifully combined here:
> 
> typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;

It is indeed beautiful. Want to write a DIP to switch to < > ?
January 30, 2019
On Wed, Jan 30, 2019 at 05:11:07PM -0800, Walter Bright via Digitalmars-d wrote:
> On 1/30/2019 4:08 PM, Andrei Alexandrescu wrote:
> > Don't forget "typename" and "::template", beautifully combined here:
> > 
> > typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;
> 
> It is indeed beautiful. Want to write a DIP to switch to < > ?

I second!

And while we're at it, how about reinstating the comma operator and introducing opComma, and additionally opLess, opLessEqual, opGreater, opGreaterEqual, opNotEqual, and opDot?  It will be greatly helpful with a library implementation of < > syntax, which will be an important step to gauge how useful it will be in practice, and could in the meantime serve as a good substitute in lieu of a complicated in-compiler implementation.


T

-- 
Making non-nullable pointers is just plugging one hole in a cheese grater. -- Walter Bright
January 30, 2019
On Wed, Jan 30, 2019 at 5:15 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On 1/30/2019 4:08 PM, Andrei Alexandrescu wrote:
> > Don't forget "typename" and "::template", beautifully combined here:
> >
> > typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;
>
> It is indeed beautiful. Want to write a DIP to switch to < > ?

Bauss will win another worst code contest if this DIP gets approved ;-)
January 31, 2019
On Thursday, 31 January 2019 at 01:28:29 UTC, H. S. Teoh wrote:
>
> And while we're at it, how about reinstating the comma operator and introducing opComma, and additionally opLess, opLessEqual, opGreater, opGreaterEqual, opNotEqual, and opDot?  It will be greatly helpful with a library implementation of < > syntax, which will be an important step to gauge how useful it will be in practice, and could in the meantime serve as a good substitute in lieu of a complicated in-compiler implementation.
>
>
> T

Also an opAnd
January 31, 2019
On Thursday, 31 January 2019 at 01:28:29 UTC, H. S. Teoh wrote:
> On Wed, Jan 30, 2019 at 05:11:07PM -0800, Walter Bright via Digitalmars-d wrote:
>> On 1/30/2019 4:08 PM, Andrei Alexandrescu wrote:
>> > Don't forget "typename" and "::template", beautifully combined here:
>> > 
>> > typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;
>> 
>> It is indeed beautiful. Want to write a DIP to switch to < > ?
>
> I second!
>
> And while we're at it, how about reinstating the comma operator and introducing opComma, and additionally opLess, opLessEqual, opGreater, opGreaterEqual, opNotEqual, and opDot?  It will be greatly helpful with a library implementation of < > syntax, which will be an important step to gauge how useful it will be in practice, and could in the meantime serve as a good substitute in lieu of a complicated in-compiler implementation.
>
>
> T

FWIW opDot still exists in DMD as of 2.084.0 (and nightly):

https://github.com/dlang/dmd/blob/2457038c1ac37fbe1098b4b3d98007761149dfaf/test/runnable/xtest46.d#L130

It's just deprecated.
We don't have opGreater/opEqual, but there's still opAnd:

https://github.com/dlang/dmd/blob/06d3770d3baf51ce0b4b9998bf6a4e0369ee8f02/test/runnable/opover.d

In fact all these old D1 operator overloads (opPos,opNeg,..., opShl, opShr,..., opMul_r) are still supported in DMD and don't even trigger a deprecation message:

https://github.com/dlang/dmd/blob/06d3770d3baf51ce0b4b9998bf6a4e0369ee8f02/src/dmd/id.d#L206

January 31, 2019
On Thursday, 31 January 2019 at 13:01:09 UTC, Seb wrote:
> On Thursday, 31 January 2019 at 01:28:29 UTC, H. S. Teoh wrote:
>> On Wed, Jan 30, 2019 at 05:11:07PM -0800, Walter Bright via Digitalmars-d wrote:
>>> On 1/30/2019 4:08 PM, Andrei Alexandrescu wrote:
>>> > Don't forget "typename" and "::template", beautifully combined here:
>>> > 
>>> > typedef typename Allocator::template rebind<Mapped>::other mapped_type_allocator;
>>> 
>>> It is indeed beautiful. Want to write a DIP to switch to < > ?
>>
>> I second!
>>
>> And while we're at it, how about reinstating the comma operator and introducing opComma, and additionally opLess, opLessEqual, opGreater, opGreaterEqual, opNotEqual, and opDot?
>>  It will be greatly helpful with a library implementation of <
>> > syntax, which will be an important step to gauge how useful
>> it will be in practice, and could in the meantime serve as a good substitute in lieu of a complicated in-compiler implementation.
>>
>>
>> T
>
> FWIW opDot still exists in DMD as of 2.084.0 (and nightly):
>
> https://github.com/dlang/dmd/blob/2457038c1ac37fbe1098b4b3d98007761149dfaf/test/runnable/xtest46.d#L130
>
> It's just deprecated.
> We don't have opGreater/opEqual, but there's still opAnd:
>
> https://github.com/dlang/dmd/blob/06d3770d3baf51ce0b4b9998bf6a4e0369ee8f02/test/runnable/opover.d
>
> In fact all these old D1 operator overloads (opPos,opNeg,..., opShl, opShr,..., opMul_r) are still supported in DMD and don't even trigger a deprecation message:
>
> https://github.com/dlang/dmd/blob/06d3770d3baf51ce0b4b9998bf6a4e0369ee8f02/src/dmd/id.d#L206

Someone needs to do some cleanup.