View mode: basic / threaded / horizontal-split · Log in · Help
August 25, 2012
bug with std.range.zip? range with opEquals(const) const not allowed inside zip
is that a bug? should i file a bug report?

---
import std.range;
struct A{
	int x;
	//bool opEquals(const A a) {return a.x==x;} //comiles when this 
is used
	//bool opEquals(const A a)const{return a.x==x;} //will not 
compile
        bool opEquals(A a)const{return a.x==x;} //will not compile
}

struct Range(S){
	auto front(){return 0;}
	auto popFront(){}
	auto empty(){return false;}
}

void main(){
	auto a=Range!A();
	zip(a,a);
}
----

phobos/std/range.d(3449): Error: function 
std.typecons.Tuple!(Range!(A),Range!(A)).Tuple.opEquals!(const(Tuple!(Range!(A),Range!(A)))).opEquals 
(const(Tuple!(Range!(A),Range!(A))) rhs) is not callable using 
argument types (const(Tuple!(Range!(A),Range!(A)))) const
phobos/std/range.d(3811): Error: template instance 
std.range.Zip!(Range!(A),Range!(A)) error instantiating
scratchd(26):        instantiated from here: 
zip!(Range!(A),Range!(A))
test_scratch.d(26): Error: template instance 
std.range.zip!(Range!(A),Range!(A)) error instantiating



related question:
what is the "standard " signature for opEquals ?
is it:
        bool opEquals(const ref A a)const
        bool opEquals(A a)const
        bool opEquals(A a)
?
August 25, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
On Saturday, August 25, 2012 21:58:12 timotheecour wrote:
> is that a bug? should i file a bug report?

I'd have to study it more to say, but std.algorithm doesn't play very nicely 
with const right now. More work needs to be done in that area, and stuff like 
enhancement# 8407 would help considerably. I'm pretty sure that there's at 
least one compiler bug making it really hard for some portions of it to be 
const correct at the moment as well, but I can't remember what it was right 
now (and I could remember incorrectly).

Your problem here may or may not be related to that. But if you can't get zip 
to play nicely with your struct when it has the proper signatures for 
opEquals, then please report it.

> what is the "standard " signature for opEquals ?

If you're using const, it's two functions:

bool opEquals(const S rhs} const {...}
bool opEquals(const ref S rhs) const {...}

If you're not using const or you want it to work without const, then you 
use/add

bool opEquals(S rhs) { ... }
bool opEquals(ref S rhs) {...}

Hopefully, we sort out the ref situation one of these days so that only one 
function is needed (at least as long as using const is okay) rather than two, 
but for now, this is what we get.

- Jonathan M Davis
August 25, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
thanks for the quick answer! I filed bug report 
http://d.puremagic.com/issues/show_bug.cgi?id=8584
August 26, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
Jonathan M Davis wrote:
> On Saturday, August 25, 2012 21:58:12 timotheecour wrote:
> > is that a bug? should i file a bug report?
> 
> I'd have to study it more to say, but std.algorithm doesn't play very nicely 
> with const right now. More work needs to be done in that area, and stuff like 
> enhancement# 8407 would help considerably. I'm pretty sure that there's at 
> least one compiler bug making it really hard for some portions of it to be 
> const correct at the moment as well, but I can't remember what it was right 
> now (and I could remember incorrectly).
> 
> Your problem here may or may not be related to that. But if you can't get zip 
> to play nicely with your struct when it has the proper signatures for 
> opEquals, then please report it.
> 
> > what is the "standard " signature for opEquals ?
> 
> If you're using const, it's two functions:
> 
> bool opEquals(const S rhs} const {...}
> bool opEquals(const ref S rhs) const {...}
> 
> If you're not using const or you want it to work without const, then you 
> use/add
> 
> bool opEquals(S rhs) { ... }
> bool opEquals(ref S rhs) {...}
> 
> Hopefully, we sort out the ref situation one of these days so that only one 
> function is needed (at least as long as using const is okay) rather than two, 
> but for now, this is what we get.

What is the ref situation?
I thought ref is used as an optimization that allows passing lvalues
more efficiently whereas without ref is needed for rvalues.

Jens
August 26, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
On Sunday, August 26, 2012 14:47:38 Jens Mueller wrote:
> What is the ref situation?
> I thought ref is used as an optimization that allows passing lvalues
> more efficiently whereas without ref is needed for rvalues.

ref doesn't necessarily have anything to do with optimizations. It makes it so 
that any operations done on the function parameter inside the function are 
also done on the variable passed in. The parameter is essentially an alias for 
the variable passed in.

You can choose to use ref in order to avoid a copy, but it's also arguably bad 
practice to have a function take an argument by ref if it's not actually going 
to mutate the original, since that's confusing.

_const_ ref is more for avoiding the copy, since it's like ref except that you 
can't actually mutate the variable. So, it makes sense to use const ref 
specifically to avoid unnecessary copies.

However, while in C++, you can pass rvalues to const&, in D, you can't. It 
doesn't matter if the ref is const or not, it still requires an lvalue. This 
solves certain issues caused by C++'s choice (issues primarily related to 
function overloading IIRC), but it makes it rather difficult to declare a single 
function which takes either an lvalue or an rvalue but which tries to avoid 
unnecessary copying.

D's auto ref essentially does it (rvalues are then always passed by rvalue and 
lvalues are always passed by lvalue), but it only works with templates, 
because it has to create two versions of the function.

So, what we'd _like_ to have is a solution where you can mark a parameter in a 
way similar to auto ref or C++s const& and have the function not care whether 
it's passed an lvalue or rvalue and have it avoid copying as much as possible 
and have it work with _all_ function types, not just templated ones, but we 
haven't sorted out how to do that yet. _That's_ the ref situation that needs 
to be solved.

- Jonathan M Davis
August 27, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
Jonathan M Davis wrote:
> On Sunday, August 26, 2012 14:47:38 Jens Mueller wrote:
> > What is the ref situation?
> > I thought ref is used as an optimization that allows passing lvalues
> > more efficiently whereas without ref is needed for rvalues.
> 
> ref doesn't necessarily have anything to do with optimizations. It makes it so 
> that any operations done on the function parameter inside the function are 
> also done on the variable passed in. The parameter is essentially an alias for 
> the variable passed in.
> 
> You can choose to use ref in order to avoid a copy, but it's also arguably bad 
> practice to have a function take an argument by ref if it's not actually going 
> to mutate the original, since that's confusing.
> 
> _const_ ref is more for avoiding the copy, since it's like ref except that you 
> can't actually mutate the variable. So, it makes sense to use const ref 
> specifically to avoid unnecessary copies.

This is what I meant.

> However, while in C++, you can pass rvalues to const&, in D, you can't. It 
> doesn't matter if the ref is const or not, it still requires an lvalue. This 
> solves certain issues caused by C++'s choice (issues primarily related to 
> function overloading IIRC), but it makes it rather difficult to declare a single 
> function which takes either an lvalue or an rvalue but which tries to avoid 
> unnecessary copying.
> 
> D's auto ref essentially does it (rvalues are then always passed by rvalue and 
> lvalues are always passed by lvalue), but it only works with templates, 
> because it has to create two versions of the function.
>
> So, what we'd _like_ to have is a solution where you can mark a parameter in a 
> way similar to auto ref or C++s const& and have the function not care whether 
> it's passed an lvalue or rvalue and have it avoid copying as much as possible 
> and have it work with _all_ function types, not just templated ones, but we 
> haven't sorted out how to do that yet. _That's_ the ref situation that needs 
> to be solved.

Aha. I see.
Then we get down from four declarations to two by writing
bool opEquals(const auto ref S rhs) const {...}
and
bool opEquals(auto ref S rhs) {...}

And with inout probably even further:
bool opEquals(inout auto ref S rhs) inout {...}

Thanks for explaining.

Jens
August 27, 2012
Re: bug with std.range.zip? range with opEquals(const) const not allowed inside zip
On Monday, August 27, 2012 09:42:34 Jens Mueller wrote:
> Aha. I see.
> Then we get down from four declarations to two by writing
> bool opEquals(const auto ref S rhs) const {...}
> and
> bool opEquals(auto ref S rhs) {...}
> 
> And with inout probably even further:
> bool opEquals(inout auto ref S rhs) inout {...}
> 
> Thanks for explaining.

auto ref _only_ works with templated functions, and I'm not sure if it even 
works to templatize opEquals (it might; it might not). So, while auto ref 
helps in some cases, in many it does not.

- Jonathan M Davis
Top | Discussion index | About this forum | D home