Thread overview
Convert array to custom type when passing function argument
Apr 17, 2019
Stefanos Baziotis
Apr 17, 2019
Adam D. Ruppe
Apr 17, 2019
Stefanos Baziotis
Apr 17, 2019
Adam D. Ruppe
Apr 17, 2019
Stefanos Baziotis
Apr 17, 2019
Adam D. Ruppe
Apr 18, 2019
Stefanos Baziotis
Apr 19, 2019
Ali Çehreli
April 17, 2019
I have a custom Buf struct (working as a simple vector)

struct Buf(T) {
    size_t cap, len;
    T *data;

    @nogc
    this(T[] arr) {
        reserve(arr.length);
        foreach(item; arr) {
            push(item);
        }
    }
    ...
};

And I have a function like this:

void test(Buf!(int) buf) {
}

I want to be able to make it work array-like to have compact function calls.
Something like this:
test([1,2,3]);

Currently I have the constructor shown and with that I do:
test(Buf!(int)([1,2,3]);
which is compact but can it be done differently? Meaning, if a function takes
a Buf!(T), can it also take a T[] and construct a Buf!(T) using some constructor?

Thanks in advance!
April 17, 2019
On Wednesday, 17 April 2019 at 12:20:49 UTC, Stefanos Baziotis wrote:
> I want to be able to make it work array-like to have compact function calls.
> Something like this:
> test([1,2,3]);

This is the "implicit construction" I sometimes talk about.... and D doesn't support it, by design (alas).

There's two options you can do:

1) offer an overload to your function that does the conversion:

void test(Buf!int arr) { /* impl here */ }
void test(int[] arr) { test(Buf!int(arr)); } // just forward to the other

or

2) Offer a helper construction function you can call, like:

Buf!int toBuf(int[] a) { return Buf!int(a); }

and then you can call the  function like

test([1, 2, 3].toBuf); // calling your function at the end

April 17, 2019
On Wednesday, 17 April 2019 at 12:48:52 UTC, Adam D. Ruppe wrote:
>
> This is the "implicit construction" I sometimes talk about.... and D doesn't support it, by design (alas).
>

Sorry if this has been asked again, I didn't find anything.
Do we know the reason why it is not supported?

> There's two options you can do:
>
> 1) offer an overload to your function that does the conversion:
>
> void test(Buf!int arr) { /* impl here */ }
> void test(int[] arr) { test(Buf!int(arr)); } // just forward to the other
>
> or
>
> 2) Offer a helper construction function you can call, like:
>
> Buf!int toBuf(int[] a) { return Buf!int(a); }
>
> and then you can call the  function like
>
> test([1, 2, 3].toBuf); // calling your function at the end

Yes, I had done the 2), which means for 50 functions, I have another 50 functions.
Because of the constructor these are one-liners but still, it's kind of ugly.

I didn't know about the 3) thanks! I think it's not a very good solution for this
kind of problems but cool otherwise.

- Stefanos


April 17, 2019
On Wednesday, 17 April 2019 at 15:23:06 UTC, Stefanos Baziotis wrote:
> Sorry if this has been asked again, I didn't find anything.
> Do we know the reason why it is not supported?

Basically implicit construction was considered a mistake in C++ and D didn't want to repeat that mistake. Most code guides for C++ say to always (or almost always) mark your constructors with `explicit`, so D just makes that the only option.

I argue C++'s mistake was *out-out* implicit construction, not the concept in general - I kinda wish D would allow it if you specifically asked for it in the type.

Walter also says though implicit construction complicates function overloading rules and compiler error messages, and he doesn't think it is worth the cost to even try it with a new keyword (IIRC, I haven't had this chat with him for a while, so I might be misremembering). Again, his experience with it in C++ on several levels was negative and he wanted to simplify D so people are more likely to do the right thing.

I actually agree with him 90% of the time... just I wish it was available there for the other cases still.
April 17, 2019
On Wednesday, 17 April 2019 at 16:33:17 UTC, Adam D. Ruppe wrote:
>
> [...]
>

Thanks for the info!

> I argue C++'s mistake was *out-out* implicit construction

What do you mean by out-out?

- Stefanos
April 17, 2019
On Wednesday, 17 April 2019 at 23:26:16 UTC, Stefanos Baziotis wrote:
>> I argue C++'s mistake was *out-out* implicit construction
>
> What do you mean by out-out?

In C++, if you define a struct/class, and constructors apply for this.

struct Test {
   Test(const char* foo) {}
};

void cool(Test t) {}

cool("string"); // works


That works in C++, unless you mark that constructor with `explicit`


struct Test {
   explicit Test(const char* foo) {} // this opts out of the cool thing above
};
April 18, 2019
On Wednesday, 17 April 2019 at 23:44:42 UTC, Adam D. Ruppe wrote:
>
> In C++, if you define a struct/class, and constructors apply for this.
>
> struct Test {
>    Test(const char* foo) {}
> };
>
> void cool(Test t) {}
>
> cool("string"); // works
>
>
> That works in C++, unless you mark that constructor with `explicit`
>
>
> struct Test {
>    explicit Test(const char* foo) {} // this opts out of the cool thing above
> };

Yes, thanks. :)

Actually, I asked initially because in C++ you can do the thing I described.
I thought that you meant something I missed with out-out.

- Stefanos


April 19, 2019
On 04/17/2019 05:21 PM, Stefanos Baziotis wrote:
> On Wednesday, 17 April 2019 at 23:44:42 UTC, Adam D. Ruppe wrote:

>>    explicit Test(const char* foo) {} // this opts out of the cool
>> thing above

> Actually, I asked initially because in C++ you can do the thing I
> described.
> I thought that you meant something I missed with out-out.

So, Adam meant opt-out but wrote out-out. :)

Ali