Jump to page: 1 2
Thread overview
Fix template parameter
Aug 08, 2022
Dom Disc
Aug 08, 2022
bauss
Aug 08, 2022
Dom Disc
Aug 09, 2022
pascal111
Aug 09, 2022
Meta
Aug 09, 2022
Paul Backus
Aug 09, 2022
Dom Disc
Aug 09, 2022
Dom Disc
Aug 09, 2022
Paul Backus
Aug 10, 2022
Dom Disc
Aug 10, 2022
Nick Treleaven
August 08, 2022

Hello.
I found in the documentation functions declared like this:

pure @nogc @safe BigInt opAssign(T : BigInt)(T x);

What is the difference to declaring it like:

pure @nogc @safe BigInt opAssign(BigInt x);

To me the first declaration seems to be unnecessarily bloated, so I ask myself: does it provide any kind of advantage? I can't see it.

August 08, 2022

On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:

>
pure @nogc @safe BigInt opAssign(T : BigInt)(T x);

This will only be included in the object file if used.

>

What is the difference to declaring it like:

pure @nogc @safe BigInt opAssign(BigInt x);

This will always be in the object file.

Someone can correct me if I'm wrong, but I think it's mostly linkage optimization.

August 08, 2022

On 8/8/22 8:02 AM, Dom Disc wrote:

>

Hello.
I found in the documentation functions declared like this:

pure @nogc @safe BigInt opAssign(T : BigInt)(T x);

What is the difference to declaring it like:

pure @nogc @safe BigInt opAssign(BigInt x);

To me the first declaration seems to be unnecessarily bloated, so I ask myself: does it provide any kind of advantage? I can't see it.

Just a guess, but there was a time in the distant past when you could not overload template functions with regular functions. Perhaps that's why?

Otherwise, no there really isn't a difference in this case.

-Steve

August 08, 2022

On Monday, 8 August 2022 at 12:46:48 UTC, bauss wrote:

>

On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:

>
pure @nogc @safe BigInt opAssign(T : BigInt)(T x);

This will only be included in the object file if used.

>
pure @nogc @safe BigInt opAssign(BigInt x);

This will always be in the object file.

Ah, ok. But shouldn't the linker throw it out of an executable, if it is not used?
I mean, even the most dump linker should be able to do this basic optimization...

August 09, 2022
On Monday, 8 August 2022 at 14:48:27 UTC, Dom Disc wrote:
> On Monday, 8 August 2022 at 12:46:48 UTC, bauss wrote:
>> On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:
>>>
>>> ```D
>>> pure @nogc @safe BigInt opAssign(T : BigInt)(T x);
>>> ```
>>
>> This will only be included in the object file if used.
>>
>>> ```D
>>> pure @nogc @safe BigInt opAssign(BigInt x);
>>> ```
>>
>> This will always be in the object file.
>
> Ah, ok. But shouldn't the linker throw it out of an executable, if it is not used?
> I mean, even the most dump linker should be able to do this basic optimization...

I didn't study this level yet in templates, but did you ask about if changing compiler can make a difference to what you desire? I know that there are gdc, ldc and dmd compilers. DMD is the most common one, I think.


August 09, 2022

On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:

>

Hello.
I found in the documentation functions declared like this:

pure @nogc @safe BigInt opAssign(T : BigInt)(T x);

This is a template function, even if T is constrained to always be BigInt (it may also include anything that is a subtype of BigInt... I've received different answers on what exactly (T: SomeType) means in this context). This means that it cannot be virtual, you can't take its address, and as bauss said, it won't show up in the object file if it's not used.

As far as I know, there's no advantage to doing this over opAssign(BigInt x), UNLESS (T: BigInt) means "BigInt and any subtype of BigInt", in which case the advantage is similar to doing <T extends BigInt> void opAssign(T val) in Java (referring to polymorphism; this won't give you virtual dispatch like it does in Java).

August 09, 2022

On Tuesday, 9 August 2022 at 21:08:52 UTC, Meta wrote:

>

(it may also include anything that is a subtype of BigInt... I've received different answers on what exactly (T: SomeType) means in this context).

Yes, this syntax allows anything that implicitly converts to BigInt; for example:

import std.bigint;

void fun(T : BigInt)(T t)
{
    pragma(msg, "Instantiated with T = `" ~ T.stringof ~ "`");
}

struct S
{
    BigInt n;
    alias n this;
}

void main()
{
    S s;
    fun(s); // Instantiated with T = `S`
}

There is currently no way to write a template specialization that requires an exact type, with no implicit conversions. For that, you would have to use a template constraint instead:

void fun(T)(T t)
if (is(T == BigInt))
{
    // ...
}
August 09, 2022

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:

>

Yes, this syntax allows anything that implicitly converts to BigInt; for example:

import std.bigint;

void fun(T : BigInt)(T t)
{
    pragma(msg, "Instantiated with T = `" ~ T.stringof ~ "`");
}

struct S
{
    BigInt n;
    alias n this;
}

void main()
{
    S s;
    fun(s); // Instantiated with T = `S`
}

Aha. But isn't that also true for the other declaration?

void fun(BigInt t) { }

will also accept anything that implicitly converts to BigInt, no?
So I still don't see the big difference.
Except that is is a template - for what ever that may be useful if it doesn't take more than one type.
Relying on something as subtle as this difference does have a code-smell for me.

August 09, 2022

On Tuesday, 9 August 2022 at 22:32:23 UTC, Dom Disc wrote:

>

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:

>

Yes, this syntax allows anything that implicitly converts to BigInt;

Oh, or do you mean I will get two different instances of the template, if I call it with two different types with implicit conversion?
That would make it even worse than the non-templated declaration!

August 09, 2022

On Tuesday, 9 August 2022 at 22:36:23 UTC, Dom Disc wrote:

>

On Tuesday, 9 August 2022 at 22:32:23 UTC, Dom Disc wrote:

>

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:

>

Yes, this syntax allows anything that implicitly converts to BigInt;

Oh, or do you mean I will get two different instances of the template, if I call it with two different types with implicit conversion?
That would make it even worse than the non-templated declaration!

Yes, exactly.

« First   ‹ Prev
1 2