www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Arrays of variants, C++ vs D

reply JN <666total wp.pl> writes:
This C++ code compiles:
```cpp
#include <variant>
#include <string>
#include <map>

int main()
{
     using Foo = std::variant<int, std::string>;
     std::map<int, Foo> foos =  {{0, "abc"}, {1, 5}};
}

This code doesn't:

```d
import std.variant;

void main()
{
     alias Foo = Algebraic!(int, string);
     Foo[int] foos = [
         0: "abc",
         1: 5
     ];
}
```
but this does:

```d
import std.variant;

void main()
{
     alias Foo = Algebraic!(int, string);
     Foo[int] foos = [
         0: Foo("abc"),
         1: Foo(5)
     ];
}
```

Why does D need the explicit declarations whereas C++ can infer 
it?
Jun 17
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jun 17, 2021 at 07:44:31PM +0000, JN via Digitalmars-d-learn wrote:
[...]
     Foo[int] foos = [
         0: Foo("abc"),
         1: Foo(5)
     ];
 }
 ```
 
 Why does D need the explicit declarations whereas C++ can infer it?
Because D does not support implicit construction. The array literal is parsed as-is, meaning string[int] is inferred rather than Foo[int]. So the initialization fails because of a type mismatch. Implicit construction has been asked for many times, but Walter has been adamant about not allowing implicit construction in D. T -- Music critic: "That's an imitation fugue!"
Jun 17
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/17/21 4:15 PM, H. S. Teoh wrote:
 On Thu, Jun 17, 2021 at 07:44:31PM +0000, JN via Digitalmars-d-learn wrote:
 [...]
      Foo[int] foos = [
          0: Foo("abc"),
          1: Foo(5)
      ];
 }
 ```

 Why does D need the explicit declarations whereas C++ can infer it?
Because D does not support implicit construction. The array literal is parsed as-is, meaning string[int] is inferred rather than Foo[int]. So the initialization fails because of a type mismatch.
Implicit construction is supported: struct Foo { int x; this(int y) { x = y; } } Foo f = 5; // ok implicit construction What is happening here though is that the construction is being done as an AA literal. This works for *some* types, but not all. e.g.: Foo[int] f = [5 : 5]; // error double[int] f = [5 : 5]; // ok It really should work IMO. -Steve
Jun 17
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/17/21 1:46 PM, Steven Schveighoffer wrote:

 Implicit construction is supported:

 struct Foo
 {
     int x;
     this(int y) { x = y; }
 }

 Foo f = 5; // ok implicit construction
That's so unlike the rest of the language that I consider it to be a bug. :) Really, why? What if the expression is more complicated: int i() { return 1; } Foo f = i(); OK, that works as well. Wow! But the following doesn't and is what I think Walter has been trying to prevent: struct Foo { int x; this(int y) { x = y; } } void foo(Foo) { } void main() { foo(42); // COMPILATION ERROR } What's the difference? In both cases an int is being converted to a Foo. I think the "working" case is against the design of D. Likely there is a subtlety that I am missing... Ali
Jun 17
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/17/21 5:01 PM, Ali Çehreli wrote:

 
 What's the difference? In both cases an int is being converted to a Foo. 
 I think the "working" case is against the design of D.
 
 Likely there is a subtlety that I am missing...
The difference might be that construction has only one set of overloads -- the constructor of the item being created. With your example, there's the set of overloads to create a Foo and the set of overloads to call foo. Imagine this: struct Foo { int x; this(int y) { x = y; } } struct Bar { int x; this(int y) { x = y; } } void foo(Foo f){} void foo(Bar b){} void main() { foo(42); // which one? } But I don't know. I know that there are all kinds of subtle problems with C++ implicit conversions, and D is right to avoid all that. But this might be one case where the decision tree is easy. -Steve
Jun 17