www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Const vs Non const method

reply Andrea Fontana <nospam example.com> writes:
Check this simple code:
http://dpaste.dzfl.pl/2772c9144f1c

I can't understand how to minimize code duplication for function 
like get().
Of course on real case body is much bigger and complex than that.

The only way I found is to move the body of function inside a 
mixin template:

mixin template getterImpl()
{
    auto getterImpl() { /* very long body */ return inner; }
}

and then:

auto get() const { mixin getterImpl; return getterImpl; }
auto get() { mixin getterImpl; return getterImpl; }

Am I missing something? I don't think it's the right way.
Feb 25 2016
next sibling parent reply Namespace <rswhite4 gmail.com> writes:
Try inout:
----
import std.stdio;

struct Inner
{
	int field = 3;
}

struct Test
{
	
	auto get() inout { return inner; }
	
	private Inner inner;
}


void main()
{
	
	{
		Test test;
		test.get.field = 4;
	}
	
	{
		immutable Test test;
		writeln(test.get.field);
	}
}
----
Feb 25 2016
parent Andrea Fontana <nospam example.com> writes:
On Thursday, 25 February 2016 at 10:48:34 UTC, Namespace wrote:
 Try inout:
 ----
 import std.stdio;

 struct Inner
 {
 	int field = 3;
 }

 struct Test
 {
 	
 	auto get() inout { return inner; }
 	
 	private Inner inner;
 }


 void main()
 {
 	
 	{
 		Test test;
 		test.get.field = 4;
 	}
 	
 	{
 		immutable Test test;
 		writeln(test.get.field);
 	}
 }
 ----
Uh, I didn't know inout can be used with function. I think it was used only with params/return. Thank you :)
Feb 25 2016
prev sibling parent reply Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Thursday, 25 February 2016 at 10:44:49 UTC, Andrea Fontana 
wrote:
 Check this simple code:
 http://dpaste.dzfl.pl/2772c9144f1c

 I can't understand how to minimize code duplication for 
 function like get().
 Of course on real case body is much bigger and complex than 
 that.

 The only way I found is to move the body of function inside a 
 mixin template:

 mixin template getterImpl()
 {
    auto getterImpl() { /* very long body */ return inner; }
 }

 and then:

 auto get() const { mixin getterImpl; return getterImpl; }
 auto get() { mixin getterImpl; return getterImpl; }

 Am I missing something? I don't think it's the right way.
You can do this using inout: http://dpaste.dzfl.pl/678cac023051 That getter can be written even shorter due to a quirk in the D syntax, like: inout get() { return inner; } But I prefer to explicitly state inout for every parameter and return type. inout is kind of a wildcard for mutable, const, and immutable. You can also add it to your function parameters, for example: inout(int[]) doSomething(inout(SomeClass) c); So the constness of doSomething's return type depends on the constness of the passed argument.
Feb 25 2016
parent reply Namespace <rswhite4 gmail.com> writes:
On Thursday, 25 February 2016 at 10:59:43 UTC, Rene Zwanenburg 
wrote:
 On Thursday, 25 February 2016 at 10:44:49 UTC, Andrea Fontana 
 wrote:
 Check this simple code:
 http://dpaste.dzfl.pl/2772c9144f1c

 I can't understand how to minimize code duplication for 
 function like get().
 Of course on real case body is much bigger and complex than 
 that.

 The only way I found is to move the body of function inside a 
 mixin template:

 mixin template getterImpl()
 {
    auto getterImpl() { /* very long body */ return inner; }
 }

 and then:

 auto get() const { mixin getterImpl; return getterImpl; }
 auto get() { mixin getterImpl; return getterImpl; }

 Am I missing something? I don't think it's the right way.
You can do this using inout: http://dpaste.dzfl.pl/678cac023051 That getter can be written even shorter due to a quirk in the D syntax, like: inout get() { return inner; } But I prefer to explicitly state inout for every parameter and return type. inout is kind of a wildcard for mutable, const, and immutable. You can also add it to your function parameters, for example: inout(int[]) doSomething(inout(SomeClass) c); So the constness of doSomething's return type depends on the constness of the passed argument.
What would be the C++ way? Is there any comfortable way to solve this problem in a nice way like D?
Mar 06 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 6 March 2016 at 17:53:47 UTC, Namespace wrote:
 What would be the C++ way? Is there any comfortable way to 
 solve this problem in a nice way like D?
C++ has a non-idiomatic language culture. There are many ways to do it. One clean way could be to use a templated method, another way is to use a function object, a dirty way would be to use a const-cast.
Mar 07 2016
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 7 March 2016 at 10:52:53 UTC, Ola Fosheim Grøstad 
wrote:
 On Sunday, 6 March 2016 at 17:53:47 UTC, Namespace wrote:
 What would be the C++ way? Is there any comfortable way to 
 solve this problem in a nice way like D?
C++ has a non-idiomatic language culture. There are many ways to do it. One clean way could be to use a templated method, another way is to use a function object, a dirty way would be to use a const-cast.
Another thing in C++ is that you can overload members on rvalue and lvalue references, from http://en.cppreference.com/w/cpp/language/member_functions : #include <iostream> struct S { void f() & { std::cout << "lvalue\n"; } void f() &&{ std::cout << "rvalue\n"; } }; int main(){ S s; s.f(); // prints "lvalue" std::move(s).f(); // prints "rvalue" S().f(); // prints "rvalue" } Of course, all of this is just because you don't get to specify the type of the "this" pointer... So not as clean as it should be, but that applies to both languages. Adding lots of syntax with no real semantic benefits.
Mar 07 2016
prev sibling parent reply Namespace <rswhite4 gmail.com> writes:
Let's use an example:

----
import std.stdio;

class Visitor {
public:
     void visit(inout A) {
         writeln("visit A");
     }

     void visit(inout B) {
         writeln("visit B");
     }
}

class A {
public:
     void accept(Visitor v) inout {
         v.visit(this);
     }
}

class B : A {
public:
     override void accept(Visitor v) inout {
         v.visit(this);
     }
}
----

This piece of code works for both versions below:

#1:
----
void main() {
     A a = new A();
     A b = new B();

     Visitor v = new Visitor();

     a.accept(v);
     b.accept(v);
}
----

#2:
----
void main() {
     const A a = new A();
     const A b = new B();

     Visitor v = new Visitor();

     a.accept(v);
     b.accept(v);
}
----

Thanks to the wildcard modifier inout. Is there any possible way 
to do the same in C++?
Mar 07 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 7 March 2016 at 16:30:48 UTC, Namespace wrote:
 Thanks to the wildcard modifier inout. Is there any possible 
 way to do the same in C++?
In this specific case you could do it with a macro if you don't mind dirty macros, but you really should implement the const version explicitly or use a free function that cover both cases using templating. If you are looking for information on C++ you probably should use stack overflow: http://stackoverflow.com/questions/7792052/c-template-to-cover-const-and-non-const-method
Mar 07 2016
parent reply Namespace <rswhite4 gmail.com> writes:
On Monday, 7 March 2016 at 18:17:18 UTC, Ola Fosheim Grøstad 
wrote:
 On Monday, 7 March 2016 at 16:30:48 UTC, Namespace wrote:
 Thanks to the wildcard modifier inout. Is there any possible 
 way to do the same in C++?
In this specific case you could do it with a macro if you don't mind dirty macros, but you really should implement the const version explicitly or use a free function that cover both cases using templating. If you are looking for information on C++ you probably should use stack overflow: http://stackoverflow.com/questions/7792052/c-template-to-cover-const-and-non-const-method
Honestly speaking, I think this case is impossible to solve in C++. I'll show my fellow students the advantages of D over C++ in next couple of weeks, and this example is pretty good. :)
Mar 07 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 7 March 2016 at 18:44:01 UTC, Namespace wrote:
 Honestly speaking, I think this case is impossible to solve in 
 C++. I'll show my fellow students the advantages of D over C++ 
 in next couple of weeks, and this example is pretty good. :)
:-) Good luck!
Mar 07 2016