Thread overview
default arguments for const ref parameters in extern C++ functions
Sep 14, 2020
60rntogo
Sep 14, 2020
60rntogo
Sep 14, 2020
k2aj
Sep 14, 2020
60rntogo
Sep 15, 2020
Mathias LANG
September 14, 2020
I'm trying to use a C++ library that has a function declared like this:

---
struct Foo
{
  int x;
};

void fun(const Foo& foo = Foo(1));
---

I have translated this to a D declaration:

---
struct Foo
{
  int x;
}

extern(C++) void fun(const ref Foo foo = Foo(1));
---

This yields an error: "Foo(1) is not an lvalue and cannot be modified". I suppose this makes sense with how D references work, but I have no control over how the C++ function is declared. What can I do with this?
September 14, 2020
On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote:
> ---
> struct Foo
> {
>   int x;
> }
>
> extern(C++) void fun(const ref Foo foo = Foo(1));
> ---

I suppose this should have been:

---
extern(C++):

struct Foo
{
  int x;
}

void fun(const ref Foo foo = Foo(1));
---

Not that it changes the question in any way.
September 14, 2020
On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote:
> I'm trying to use a C++ library that has a function declared like this:
>
> ---
> struct Foo
> {
>   int x;
> };
>
> void fun(const Foo& foo = Foo(1));
> ---
>
> I have translated this to a D declaration:
>
> ---
> struct Foo
> {
>   int x;
> }
>
> extern(C++) void fun(const ref Foo foo = Foo(1));
> ---
>
> This yields an error: "Foo(1) is not an lvalue and cannot be modified". I suppose this makes sense with how D references work, but I have no control over how the C++ function is declared. What can I do with this?

AFAIK the only way to have default ref arguments is to use a global variable:
---
extern(C++) struct Foo
{
  int x;
}
immutable foo1 = Foo(1);
extern(C++) void fun(const ref Foo foo = foo1);
---
September 14, 2020
On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote:
> AFAIK the only way to have default ref arguments is to use a global variable:
> ---
> extern(C++) struct Foo
> {
>   int x;
> }
> immutable foo1 = Foo(1);
> extern(C++) void fun(const ref Foo foo = foo1);
> ---

Thanks. This appears to work, but feels like a hack. I can live with that, but I'm still wondering if there is a more idiomatic way of solving the problem.
September 15, 2020
On Monday, 14 September 2020 at 18:58:44 UTC, 60rntogo wrote:
> On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote:
>> AFAIK the only way to have default ref arguments is to use a global variable:
>> ---
>> extern(C++) struct Foo
>> {
>>   int x;
>> }
>> immutable foo1 = Foo(1);
>> extern(C++) void fun(const ref Foo foo = foo1);
>> ---
>
> Thanks. This appears to work, but feels like a hack. I can live with that, but I'm still wondering if there is a more idiomatic way of solving the problem.

D doesn't let rvalues bind to const ref (well, `in` will do that, but it's D-only).
What was described as "global variable", is more of a "manifest constant lvalue".
A (static) immutable variable with an initializer will always be CTFE-d and available at compile time, so in this case it is *exactly* what you need.

Also note that a default parameter doesn't affect the mangling / ABI, because it works exclusively on the caller side. Thus, you could just remove the default argument and your `extern(C++)` binding would work just fine. But if you want to provide the same API, `[static] immutable` + initializer is the way to go.