www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Cannot implicitly convert expression `true` of type `bool` to `Flag`

reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
std.typecons.Flag and its friends Yes and No are so trivial that I copy 
them here (and reformat for my liking):

template Flag(string name) {
   enum Flag : bool {
     no = false, yes = true
   }
}

struct Yes {
   template opDispatch(string name) {
     enum opDispatch = Flag!name.yes;
   }
}

struct No {
   template opDispatch(string name) {
     enum opDispatch = Flag!name.no;
   }
}

void main() {
   auto a = Flag!"foo".no;     // Fine
   auto b = No.foo;            // Fine

   // Error: cannot implicitly convert expression `true` of type `bool` 
to `Flag`:
   auto c = Flag!"foo"(true);
}

I think that is a wrong limitation because clearly I am being "explicit" 
there with a bool value. (I understand the issue but it exposes a 
limitation of the implementation.) I have to use the ternary operator 
e.g. after parsing a bool from program arguments:

   bool someFlag;
   // ...
   foo(someFlag ? Yes.someFlag : No.someFlag);

Spoiler alert: I will show the following function template during my 
DConf Online presentation as a workaround (or "solution"):

auto asFlag(alias variable)() {
   enum name = variable.stringof;
   enum expr = "return variable ? Yes." ~ name ~ " : No." ~ name ~ ";";
   mixin (expr);
}

That allows the following cleaner and "explicit" syntax:

   bool someFlag;
   // ...
   foo(asFlag!someFlag);

(I actually called it flagFromBool in existing code.)

However:

1) I think the standard library should already have something like that 
to remove the need for that ternary operator.

2) (This feels like something that must have been requested already.) 
While we're on the topic of removing unnecessary limitations, it would 
be nice to be able to use "not necessarily quoted string template 
arguments" just like opDispatch empowers us with.

void foo(Foo!"myFlag" myFlag) {  // <-- Ugly
}

void foo(Foo!myFlag myFlag) {    // <-- Better
}

Maybe there would be a parsing issue with the syntax but then opDispatch 
seems to be happy with it. Perhaps we should add opDispatch to 
templates? (Because I tried but failed to achieve the "better" syntax 
above with opDispatch inside (a struct inside) a template.)

If it requires a special template parameter syntax we can always abuse 
'static' further: :o)

template Flag(static string name) {
   // ...
}

Ali
Oct 15 2020
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 15 October 2020 at 21:33:32 UTC, Ali Çehreli wrote:
 void main() {
   auto a = Flag!"foo".no;     // Fine
   auto b = No.foo;            // Fine

   // Error: cannot implicitly convert expression `true` of type 
 `bool` to `Flag`:
   auto c = Flag!"foo"(true);
 }

 I think that is a wrong limitation because clearly I am being 
 "explicit" there with a bool value. (I understand the issue but 
 it exposes a limitation of the implementation.) I have to use 
 the ternary operator e.g. after parsing a bool from program 
 arguments:

   bool someFlag;
   // ...
   foo(someFlag ? Yes.someFlag : No.someFlag);
An easier way is to use a cast: bool someFlag; // ... foo(cast(Flag!"someFlag") someFlag); std.conv.to also knows how to handle this conversion: foo(someFlag.to!(Flag!"someFlag"));
Oct 15 2020
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/15/20 4:25 PM, Paul Backus wrote:

 On Thursday, 15 October 2020 at 21:33:32 UTC, Ali =C3=87ehreli wrote:
   bool someFlag;
   // ...
   foo(someFlag ? Yes.someFlag : No.someFlag);
An easier way is to use a cast: bool someFlag; // ... foo(cast(Flag!"someFlag") someFlag); std.conv.to also knows how to handle this conversion: foo(someFlag.to!(Flag!"someFlag"));
I still like the ternary operator more partly because it uses features=20 that are explained in the documentation. :) Both of your methods rely on = the fact that the implementation is a bool-based enum. Are the users=20 expected to know that? If yes, then the library can't change the=20 implementation. Ali
Oct 15 2020
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 10/15/2020 2:33 PM, Ali Çehreli wrote:
 [...]
Named parameters takes care of this.
Oct 15 2020
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Friday, 16 October 2020 at 06:50:49 UTC, Walter Bright wrote:
 On 10/15/2020 2:33 PM, Ali Çehreli wrote:
 [...]
Named parameters takes care of this.
Has anyone started to work on an implementation?
Oct 16 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 10/16/2020 2:44 AM, Andrej Mitrovic wrote:
 On Friday, 16 October 2020 at 06:50:49 UTC, Walter Bright wrote:
 On 10/15/2020 2:33 PM, Ali Çehreli wrote:
 [...]
Named parameters takes care of this.
Has anyone started to work on an implementation?
Not myself, anyway. I'm currently buried.
Oct 16 2020
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/15/20 11:50 PM, Walter Bright wrote:
 On 10/15/2020 2:33 PM, Ali =C3=87ehreli wrote:
 [...]
=20 Named parameters takes care of this.
Maybe for some people, yes. (Assuming calling with named parameters is=20 optional.) But I would still be uncomfortable defining a function with=20 naked bools like this: void foo(bool shouldDoThis, bool shouldDoThat) { // ... } The possibility of calling it wrong is still there. Is that purely the=20 caller's fault? What do others think? Ali
Oct 16 2020
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 17/10/2020 4:20 AM, Ali Çehreli wrote:
 The possibility of calling it wrong is still there. Is that purely the 
 caller's fault? What do others think?
I have never been convinced of the arguments against using bool for flags in params. But I do think that having named parameters rather than named arguments would have removed this as an issue. The name should be required.
Oct 16 2020
parent Paul Backus <snarwin gmail.com> writes:
On Friday, 16 October 2020 at 15:46:54 UTC, rikki cattermole 
wrote:
 On 17/10/2020 4:20 AM, Ali Çehreli wrote:
 The possibility of calling it wrong is still there. Is that 
 purely the caller's fault? What do others think?
I have never been convinced of the arguments against using bool for flags in params. But I do think that having named parameters rather than named arguments would have removed this as an issue. The name should be required.
It's always possible to add named parameters *in addition* to named arguments. The two are not mutually incompatible.
Oct 16 2020