template instantiation

2016-05-19 Thread vit via Digitalmars-d-learn
///Hello, i'm trying to implement d compiler and i've problems 
with some template corner cases.



class Type{}

class Foo(T : const T){
alias X = T;
}

alias Bar(T : Foo!Ts, Ts...) = Ts[0];

pragma(msg, "Foo1: ", Foo!(immutable Type).X);//Foo1: Type
pragma(msg, "Foo2: ", Foo!(Type).X);  //Foo2: Type

pragma(msg, "Bar: ", Bar!(Foo!(Type)));   //Bar: 
immutable(Type)


Last pragma attempted to extract template parameters from 
'Foo!(Type)' but since Foo!(immutable Type) == Foo!(Type) and 
Foo!(immutable Type) was instantiated first, it extracted wrong 
type.
If we change order of 1. and 2. pragma, result of 3. pragma will 
be Type and not immutable(Type).

Is this a bug?


Template instantiation

2009-03-20 Thread Trass3r

Got the following code:

public LuaState wrapClass (T) (T instance)
{
auto ptr = cast (T *) newUserdata ( (T *).sizeof);
*ptr = instance;

loadClassMetatable (typeid(T).toString);
setMetatable (-2);
return this;
}

Am I right in assuming that a different wrapClass will be created in the 
final executable for each template instantiation (e.g. calls with class 
A,B,C,... instances) and would thus bloat up the executable a bit when 
used with many classes?


Apart from that, couldn't you just use wrapClass (Object instance)? In 
the end each class instance pointer takes up the same amount of memory?!


"extern" template instantiation

2013-10-22 Thread Mathias LANG

Hi everyone,
This is going to be a silly question.

I have the following files:
-- heavy.d --
import std.regex;
enum r = 
ctRegex!(r"^(\w+)\s+([a-zA-Z0-9/]+)\?a=(\w+)&b=(\w+)&c=(\w+)([&\D+=\w+)]*)&y=([0-9A-Fa-z]+)&z=([0-9A-Fa-z]+)$");


-- main.d --
import heavy;
void main() {}

-- test.d --
import heavy;
void test() {}

So I had a Makefile, and hit compile. *BAM*
1m40s latter, I switched from GDC to DMD, and updated my dmd to 
bleeding edge.
I though it might help because of: 
http://d.puremagic.com/issues/show_bug.cgi?id=11284


$ dmd
DMD64 D Compiler v2.064-devel-b12d171

But it didn't (time make):
dmd -debug  -c main.d -ofobjs/debug//main.o
dmd -debug  -c heavy.d -ofobjs/debug//heavy.o
dmd -debug  -c test.d -ofobjs/debug//test.o
 - Linking bfake
real0m19.893s
user0m11.092s
sys 0m2.416s


With the import commented out (and make clean'ed):

dmd -debug  -c main.d -ofobjs/debug//main.o
dmd -debug  -c heavy.d -ofobjs/debug//heavy.o
dmd -debug  -c test.d -ofobjs/debug//test.o
 - Linking bfake
real0m5.636s
user0m4.124s
sys 0m0.872s

So I thought of:
public alias typeof(ctRegex!(my-super-long-string)) APIRegex;

in a .di file, but I get a linker error, and it stills need to 
instantiate the template anyway.


Can anyone point me to the right way to do this ? Thanks!


Re: template instantiation

2016-05-20 Thread tsbockman via Digitalmars-d-learn

On Thursday, 19 May 2016 at 20:14:48 UTC, vit wrote:

Is this a bug?


Yes. I've filed a report: 
https://issues.dlang.org/show_bug.cgi?id=16050


Recursive template instantiation

2017-03-13 Thread Jack Applegame via Digitalmars-d-learn
I'm pretty sure that this code should compile 
(https://dpaste.dzfl.pl/cf1e1ee6ef4b):


struct A(T) {
~this() {
char[T.sizeof] data;
}
}

struct B(T) {
A!T foo;
}

struct C {
B!C bar;
}

void main() {
C c;
}

But it doesn't:
/d300/f416.d(3): Error: struct f416.C no size because of forward 
reference /d300/f416.d(12): Error: template instance f416.B!(C) 
error instantiating


Notice that the same C++ code compiles without problems:

template struct A {
~A() {
char data[sizeof(T)];
}
};

template struct B {
A foo;
};

struct C {
B bar;
};

int main() {
C c;
}

A simple recursion is compiled successfully 
(https://dpaste.dzfl.pl/5a8ff73bfa88):


struct A(T) {
~this() {
char[T.sizeof] data;
}
}

struct C {
A!C bar;
}

void main() {
C c;
}



template instantiation question

2015-03-18 Thread Dmitri Makarov via Digitalmars-d-learn

I have three modules a.d, b.d, and c.d:

file a.d:```
module i.a;

import i.c, i.b;

final class A {
public:
  void foo() {
a.transmogrify();
  }
  S!void a;
}
```
--
file b.d:```
module i.b;

import i.a, i.c;

class B {
public:
  S!void b;
}
```
--
file c.d:```
module i.c;

struct C {}

struct S(T) {
  C transmogrify() {
return C();
  }
}
```
--
When these modules compiled separately, I assume, both a.o and 
b.o contain a definition of i.c.S!void.S.transmogrify() instance. 
Is this correct? If so, how is the symbol redefinition resolved 
when the three object files are linked into a single executable?


template instantiation problems

2020-01-10 Thread berni44 via Digitalmars-d-learn
I'm trying to understand issue 17441 [1]. I reduced it (including 
Phobos) to the following (and added some message to point out the 
problem):


test.d:
---
alias parentOf(alias sym) = __traits(parent, sym);

template packageName(alias T)
{
pragma(msg, "IN: ", T.stringof);
static if (__traits(compiles, parentOf!T))
enum parent = packageName!(parentOf!T);
else
enum string parent = null;

static if (T.stringof[0..8] == "package ")
enum packageName = (parent? parent ~ '.' : "") ~ 
T.stringof[8 .. $];

else
enum packageName = parent;
}

void main()
{
import mod0 = foo.baz;
import mod1 = foo;

pragma(msg, "mod0: ",mod0.stringof);
pragma(msg, "mod1: ",mod1.stringof);

pragma(msg, "A");
enum a = packageName!mod0;
pragma(msg, "B");
enum b = packageName!mod1;
pragma(msg, "C");

static assert(a == "foo");
static assert(b == "");  // Error: static assert:  "foo" 
== "" is false

}
---

foo/baz.d:
---
module foo.baz;
---

foo/package.d:
---
module foo;
---

When compiling with

$> dmd test.d

I get:

---
mod0: module baz
mod1: module foo
A
IN: module baz
IN: package foo
B
C
test.d(32): Error: static assert:  "foo" == "" is false
---

This clearly shows, that packageName is only instatiated once at 
top level although mod0 and mod1 are two different things (at 
least their stringof produces different results) and therefore 
should be instantiated twice.


Now I don't know if this is a bug in DMD or I should know 
something I do not know... Can you help me?


[1] https://issues.dlang.org/show_bug.cgi?id=17441


Re: Template instantiation

2009-03-20 Thread Jarrett Billingsley
On Fri, Mar 20, 2009 at 11:35 AM, Trass3r  wrote:
> Got the following code:
>
> public LuaState wrapClass (T) (T instance)
> {
>        auto ptr = cast (T *) newUserdata ( (T *).sizeof);
>        *ptr = instance;
>
>        loadClassMetatable (typeid(T).toString);
>        setMetatable (-2);
>        return this;
> }
>
> Am I right in assuming that a different wrapClass will be created in the
> final executable for each template instantiation (e.g. calls with class
> A,B,C,... instances) and would thus bloat up the executable a bit when used
> with many classes?

Yes.

> Apart from that, couldn't you just use wrapClass (Object instance)? In the
> end each class instance pointer takes up the same amount of memory?!
>

I'd say yes.  It doesn't look like there's any need for a template here.

It wouldn't be (Object*).sizeof when allocating the userdata, though;
just Object.sizeof.


Template instantiation without (...)

2010-02-07 Thread Steve Teale
Which bit of the spec for template instantiation is it that allows the 
last two lines of the following to compile and work?

import std.stdio;


struct A
{
int a;
}

template Thingie(T)
{
static if (is(T == int))
enum Thingie = 1;
else
enum Thingie = 0;
}

void main()
{
writefln("%d", Thingie!(int));
writefln("%d", Thingie!int);
writefln("%d", Thingie!A);
}


Re: "extern" template instantiation

2013-10-23 Thread Dicebot
Using `enum` with ctRegex is discouraged because it is a dumb 
copy-paste upon every enum usage. I'd recommend to use global 
variable initialized during compile-time:


```
auto r = 
ctRegex!(r"^(\w+)\s+([a-zA-Z0-9/]+)\?a=(\w+)&b=(\w+)&c=(\w+)([&\D+=\w+)]*)&y=([0-9A-Fa-z]+)&z=([0-9A-Fa-z]+)$");

```

Though it is pretty complex ctRegex and compiling it is a good 
stress test for any compiler :)


Re: "extern" template instantiation

2013-10-24 Thread Mathias LANG

On Wednesday, 23 October 2013 at 11:58:17 UTC, Dicebot wrote:
Using `enum` with ctRegex is discouraged because it is a dumb 
copy-paste upon every enum usage. I'd recommend to use global 
variable initialized during compile-time:


```
auto r = 
ctRegex!(r"^(\w+)\s+([a-zA-Z0-9/]+)\?a=(\w+)&b=(\w+)&c=(\w+)([&\D+=\w+)]*)&y=([0-9A-Fa-z]+)&z=([0-9A-Fa-z]+)$");

```

Though it is pretty complex ctRegex and compiling it is a good 
stress test for any compiler :)


Using auto was my first try. Unfortunately it has the same issue 
(slighly faster, but still "dumb C/P". So far I didn't find any 
way to tell the compiler not to compile it if I'm not using it 
(aside from versions).
As the type itself takes ages to compile, any reasonable-sized 
project with few regexes will not be able to use ctRegex in dev 
mode. I suppose there's no way to create a function that returns 
a generic ctRegex object without loosing the advantages ?


Note: The regex might seems complex, but actually isn't.
It parses an home-made REST API  based on query authentification: 
http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html 
. To me it sounded like a simple use case.


Re: "extern" template instantiation

2013-10-24 Thread Dmitry Olshansky

24-Oct-2013 20:30, Mathias LANG пишет:

On Wednesday, 23 October 2013 at 11:58:17 UTC, Dicebot wrote:

Using `enum` with ctRegex is discouraged because it is a dumb
copy-paste upon every enum usage. I'd recommend to use global variable
initialized during compile-time:

```
auto r =
ctRegex!(r"^(\w+)\s+([a-zA-Z0-9/]+)\?a=(\w+)&b=(\w+)&c=(\w+)([&\D+=\w+)]*)&y=([0-9A-Fa-z]+)&z=([0-9A-Fa-z]+)$");

```

Though it is pretty complex ctRegex and compiling it is a good stress
test for any compiler :)


Using auto was my first try. Unfortunately it has the same issue
(slighly faster, but still "dumb C/P". So far I didn't find any way to
tell the compiler not to compile it if I'm not using it (aside from
versions).
As the type itself takes ages to compile, any reasonable-sized project
with few regexes will not be able to use ctRegex in dev mode. I suppose
there's no way to create a function that returns a generic ctRegex
object without loosing the advantages ?



Something to the extent of

auto getMeARegex()
{
	static r = 
ctRegex!(r"^(\w+)\s+([a-zA-Z0-9/]+)\?a=(\w+)&b=(\w+)&c=(\w+)([&\D+=\w+)]*)&y=([0-9A-Fa-z]+)&z=([0-9A-Fa-z]+)$"); 


return r;
}

_Might_ work. Failing that make it an 0-arg template:
auto getMeARegex()(){ ... }


Note: The regex might seems complex, but actually isn't.
It parses an home-made REST API  based on query authentification:
http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html
. To me it sounded like a simple use case.



--
Dmitry Olshansky


template instantiation in D

2012-09-27 Thread Druzhinin Alexandr
Code is http://dpaste.dzfl.pl/73bd7002. And I can't understand why 
compiler instantiates SimpleFSM.execTransition!(), line #30 - I expected 
it would be instantiated only if template parameters were wrong, but it 
occurs always.

Does compiler instantiates ALL possible template specialization?


Weird template instantiation problem

2017-06-12 Thread Arafel via Digitalmars-d-learn

Hi,

I've found a strange problem, and I'm not sure if it's a bug. To give a 
bit of background, I'm implementing a multi-threaded producer-consumer 
where the next work item to be picked depends not only on the "waiting 
queue", but also on what else is being run (and potentially where) at 
the same moment, so things like "sort"'ing the queue won't probably 
work, because I don't think you use a delegate as a predicate for "sort" 
(that's what I think it would be needed to get the extra context 
information).


The idea here is that the "chooser" function returns the *index* of the 
work item to be picked.


So, the reduced problem looks like this (I've removed the extra 
information about the running jobs to make the example simpler):


```
enum defaultChooser(T) = function size_t(T[] queue) {
return 0;
};

struct S(T, size_t function(T[]) chooser = defaultChooser!T) {
}

void main() {
S!int s;
}
```

this fails and I get this:


Error: template instance S!int does not match template declaration S(T, ulong 
function(T[]) chooser = defaultChooser!T)


If instead of returning the index the actual item is returned, it works!

```
enum defaultChooser(T) = function T(T[] queue) {
return queue[0];
};

struct S(T, T function(T[]) chooser = defaultChooser!T) {
}

void main() {
S!int s;
}
```

As you can see, the only change is the type the function returns, but I 
don't see how it should make any difference.


Also, changing from "enum" to "static immutable", or even removing the 
"enum" and directly embedding the function literal doesn't seem to make 
any difference.


Any ideas on what might be going on??


Re: Recursive template instantiation

2017-03-13 Thread Jack Applegame via Digitalmars-d-learn

Is this a bug?


Re: Recursive template instantiation

2017-03-13 Thread Stefan Koch via Digitalmars-d-learn

On Monday, 13 March 2017 at 22:05:24 UTC, Jack Applegame wrote:

Is this a bug?


No it's not

struct C
{
  B!C;
}
is an error.

Howto compute C ?   <--\
let's check the members;   |
The member needs a template.   |
Howto compute the template ?   |
let's compute the parameters.  |
What is the first Parameter ?  |
Its C. |
Howoto compute C---/


Re: Recursive template instantiation

2017-03-13 Thread ag0aep6g via Digitalmars-d-learn

On 03/13/2017 03:26 PM, Jack Applegame wrote:

I'm pretty sure that this code should compile
(https://dpaste.dzfl.pl/cf1e1ee6ef4b):

struct A(T) {
~this() {
char[T.sizeof] data;
}
}

struct B(T) {
A!T foo;
}

struct C {
B!C bar;
}

void main() {
C c;
}

But it doesn't:
/d300/f416.d(3): Error: struct f416.C no size because of forward
reference /d300/f416.d(12): Error: template instance f416.B!(C) error
instantiating


It compiles when it's a normal method instead of a destructor:


struct A(T) {
void m() {
char[T.sizeof] data;
}
}
/* ... rest as above ... */


I don't see how the destructor makes a difference. Soo, bug?


Re: Recursive template instantiation

2017-03-13 Thread Stefan Koch via Digitalmars-d-learn

On Monday, 13 March 2017 at 22:59:36 UTC, ag0aep6g wrote:

On 03/13/2017 03:26 PM, Jack Applegame wrote:

I'm pretty sure that this code should compile
(https://dpaste.dzfl.pl/cf1e1ee6ef4b):

struct A(T) {
~this() {
char[T.sizeof] data;
}
}

struct B(T) {
A!T foo;
}

struct C {
B!C bar;
}

void main() {
C c;
}

But it doesn't:
/d300/f416.d(3): Error: struct f416.C no size because of 
forward
reference /d300/f416.d(12): Error: template instance 
f416.B!(C) error

instantiating


It compiles when it's a normal method instead of a destructor:


struct A(T) {
void m() {
char[T.sizeof] data;
}
}
/* ... rest as above ... */


I don't see how the destructor makes a difference. Soo, bug?


Try to use m.


Re: Recursive template instantiation

2017-03-13 Thread ag0aep6g via Digitalmars-d-learn

On 03/14/2017 12:02 AM, Stefan Koch wrote:

On Monday, 13 March 2017 at 22:59:36 UTC, ag0aep6g wrote:

[...]


struct A(T) {
void m() {
char[T.sizeof] data;
}
}
/* ... rest as above ... */


I don't see how the destructor makes a difference. Soo, bug?


Try to use m.


Works no problem?


struct A(T) {
void m() {
char[T.sizeof] data;
import std.stdio;
writeln(T.sizeof);
}
}

struct B(T) {
A!T foo;
}

struct C {
B!C bar;
}

void main() {
C c;
c.bar.foo.m();
}


Prints "1".


Re: Recursive template instantiation

2017-03-13 Thread ag0aep6g via Digitalmars-d-learn

On 03/13/2017 11:58 PM, Stefan Koch wrote:

On Monday, 13 March 2017 at 22:05:24 UTC, Jack Applegame wrote:

Is this a bug?


No it's not

struct C
{
  B!C;
}
is an error.

Howto compute C ?   <--\
let's check the members;   |
The member needs a template.   |
Howto compute the template ?   |
let's compute the parameters.  |
What is the first Parameter ?  |
Its C. |
Howoto compute C---/


I don't think that's it.

Here's a variant where B is not instantiated with C:


struct A()
{
~this() { enum s = C.sizeof; }
}

struct B() { A!() foo; }
struct C { B!() bar; }


How to compute C?
Check members.
For member `B!() bar;`, resolve `B!()`.
Check members of `B!()`.
For member `A!() foo;` resolve `A!()`.
Check members of `A!()`.
No members => size = 0 (or rather 1, I guess).
Bubble up.

But the compiler seems to get confused by the destructor. I guess it 
incorrectly(?) sees a need to analyze C again before it can finish up 
`A!()`?


Re: template instantiation question

2015-03-18 Thread Ali Çehreli via Digitalmars-d-learn

On 03/18/2015 11:03 AM, Dmitri Makarov wrote:

> When these modules compiled separately, I assume, both a.o and b.o
> contain a definition of i.c.S!void.S.transmogrify() instance.

That is very likely but I played with different three files for a while 
and failed to see that.


> how is the symbol redefinition resolved when the three object
> files are linked into a single executable?

There are different kinds of symbols. For example, the following command 
on a Linux console will show that template instances are weak symbols 
(it is not an error to have one or more weak symbols).


$ nm b.o | grep transmogrify
 W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi

'man nm' tells us that W indicates a weak symbol:

  "W"
  "w" The symbol is a weak symbol that has not been specifically
  tagged as a weak object symbol.  When a weak defined symbol is
  linked with a normal defined symbol, the normal defined symbol
  is used with no error.  When a weak undefined symbol is linked
  and the symbol is not defined, the value of the symbol is
  determined in a system-specific manner without error.  On some
  systems, uppercase indicates that a default value has been
  specified.

Ali



Re: template instantiation question

2015-03-18 Thread Dmitri Makarov via Digitalmars-d-learn

On Wednesday, 18 March 2015 at 18:26:07 UTC, Ali Çehreli wrote:

$ nm b.o | grep transmogrify
 W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi


What compiler do you use? For me, neither a.o nor b.o contain 
transmogrify definition:


$ dmd -c -Ix x/i/a.d
$ nm a.o | grep trans
 U 
_D1i1c8__T1STvZ1S12transmogrifyMFNaNbNiNfZS1i1c1C

$ dmd -c -Ix x/i/b.d
$ nm b.o | grep trans
$


Re: template instantiation question

2015-03-18 Thread Ali Çehreli via Digitalmars-d-learn

(My earlier response seems to be lost; trying one more time.)

On 03/18/2015 12:09 PM, Dmitri Makarov wrote:

> On Wednesday, 18 March 2015 at 18:26:07 UTC, Ali Çehreli wrote:
>> $ nm b.o | grep transmogrify
>>  W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi
>
> What compiler do you use?

dmd git head. I used simpler files:

// a.d
module a;

import c;
import b;

auto foo()
{
auto c = C!void();
return c.transmogrify();
}

void main()
{
assert(.foo() == b.foo());
}

// b.d
module b;

import c;

auto foo()
{
auto c = C!void();
return c.transmogrify();
}

// c.d
module c;

struct C(T) {
  int transmogrify() {
return 42;
  }
}

Then I built the program like this:

$ dmd a.d -c
$ dmd b.d -c
$ dmd c.d -c
$ dmd a.o b.o c.o

Ali



Re: template instantiation problems

2020-01-10 Thread ag0aep6g via Digitalmars-d-learn

On 10.01.20 18:27, berni44 wrote:
This clearly shows, that packageName is only instatiated once at top 
level although mod0 and mod1 are two different things (at least their 
stringof produces different results) and therefore should be 
instantiated twice.


Now I don't know if this is a bug in DMD or I should know something I do 
not know... Can you help me?



import m1 = foo.baz;
import m2 = foo;
alias p = __traits(parent, m1);

pragma(msg, m1.stringof); /* "module baz", ok */
pragma(msg, m2.stringof); /* "module foo", ok */
pragma(msg, p.stringof); /* "package foo", ok */

enum e(alias thing) = thing.stringof;

pragma(msg, e!m1); /* "module baz", ok */
pragma(msg, e!m2); /* "module foo", ok */
pragma(msg, e!p); /* "module foo", wat?? */


If you switch the last two lines around, you get "package foo" twice.

The compiler apparently thinks that m2 (module foo) and p (package foo) 
are the same thing when used as a template argument. So it reuses the 
previous result.


There's a similar issue with values:

https://issues.dlang.org/show_bug.cgi?id=14501


Re: template instantiation problems

2020-01-14 Thread Boris Carvajal via Digitalmars-d-learn

On Friday, 10 January 2020 at 18:31:59 UTC, ag0aep6g wrote:


import m1 = foo.baz;
import m2 = foo;
alias p = __traits(parent, m1);

pragma(msg, m1.stringof); /* "module baz", ok */
pragma(msg, m2.stringof); /* "module foo", ok */
pragma(msg, p.stringof); /* "package foo", ok */

enum e(alias thing) = thing.stringof;

pragma(msg, e!m1); /* "module baz", ok */
pragma(msg, e!m2); /* "module foo", ok */
pragma(msg, e!p); /* "module foo", wat?? */



Thanks for your test case.

https://github.com/dlang/dmd/pull/10724



Re: Template instantiation without (...)

2010-02-07 Thread Daniel Murphy
Steve Teale Wrote:

> Which bit of the spec for template instantiation is it that allows the 
> last two lines of the following to compile and work?
> 
> import std.stdio;
> 
> 
> struct A
> {
> int a;
> }
> 
> template Thingie(T)
> {
> static if (is(T == int))
> enum Thingie = 1;
> else
> enum Thingie = 0;
> }
> 
> void main()
> {
> writefln("%d", Thingie!(int));
> writefln("%d", Thingie!int);
> writefln("%d", Thingie!A);
> }

I suppose it's the part of the spec you're about to write a patch for.


Re: Template instantiation without (...)

2010-02-07 Thread Steve Teale
> I suppose it's the part of the spec you're about to write a patch for.

I guess so. It was discussed on one of the forums back in October 2008. I 
guess it got implemented but never made the documentation.




Re: Template instantiation without (...)

2010-02-07 Thread Steve Teale

> I suppose it's the part of the spec you're about to write a patch for.

Twas at:

http://www.digitalmars.com/d/archives/digitalmars/D/
Template_instantiation_syntax_77507.html#N77507



Reporting unsupported template instantiation

2010-08-04 Thread Kagamin
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=114518

Is there a way to report a custom error message for unsupported template 
instantiations?


0 cost template instantiation

2021-09-29 Thread Hipreme via Digitalmars-d-learn
I have a template function that all it does is given a symbol, it 
loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


The main problem is that this function is costing 2KB per 
instantiation, which is something pretty high. Specially if I 
inline, there is almost no cost when compared to its inline 
version. Trying to use pragma(inline, true) didn't do anything 
too.


If I understood correctly, mixin template would be some way to 
actually inline anything. The problem is that I can't have any 
kind of expression inside it, so, that's the only way I could 
think in how to do it.


Optimization seems to don't take care of that behaviour too.

I would like to know which approach could I take for making 
something like C's #define for that.


As this function could be really rewritten as a macro if I were 
coding in C, the cost is too high for a function that would be 
only a syntactic sugar


Weird template instantiation speed?

2023-07-09 Thread IchorDev via Digitalmars-d-learn
While working on some new bindings, I've discovered that if 
`opAssign` in a struct template "`BindingTempl(T)`" has the 
return type "`BindingTempl!T` then it adds about 4 seconds to the 
compile time per instantiation of `BindingTempl`. The added 
compile time is much lower if a function other than `opAssign` 
returns `BindingTempl!T`. Is opAssign a particularly bad operator 
to overload in templates or something?


template instantiation --- having trouble therewith

2013-09-02 Thread Carl Sturtivant


template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

Dptr!(T,U) muddle( T, U...)( Dptr!(T,U) f) {
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


The above technique seemed natural to me, but I get this message 
from dmd:


p1.d(15): Error: template p1.muddle does not match any function 
template declaration. Candidates are:

p1.d(7):p1.muddle(T, U...)(Dptr!(T, U) f)
p1.d(15): Error: template p1.muddle(T, U...)(Dptr!(T, U) f) 
cannot deduce template function from argument types !()(int 
delegate(int))


and if I use muddle!(int,int) instead it doesn't help. This is 
likely a misunderstanding on my part --- please show me how to 
sort this out.




Re: template instantiation in D

2012-09-27 Thread Druzhinin Alexandr

27.09.2012 22:48, Druzhinin Alexandr пишет:

Code is http://dpaste.dzfl.pl/73bd7002. And I can't understand why
compiler instantiates SimpleFSM.execTransition!(), line #30 - I expected
it would be instantiated only if template parameters were wrong, but it
occurs always.
Does compiler instantiates ALL possible template specialization?


Oh, I've just understood my problem - because possibility of 
execTransition!() calling can be known only in run-time, compiler should 
instantionates it too, just in case.


Good thing this newsgroup is, good thing )))


Re: Weird template instantiation problem

2017-06-12 Thread Arafel via Digitalmars-d-learn

On 06/12/2017 05:31 PM, Arafel wrote:

Hi,

I've found a strange problem, and I'm not sure if it's a bug. To give a 
bit of background, I'm implementing a multi-threaded producer-consumer 
where the next work item to be picked depends not only on the "waiting 
queue", but also on what else is being run (and potentially where) at 
the same moment, so things like "sort"'ing the queue won't probably 
work, because I don't think you use a delegate as a predicate for "sort" 
(that's what I think it would be needed to get the extra context 
information).


The idea here is that the "chooser" function returns the *index* of the 
work item to be picked.


So, the reduced problem looks like this (I've removed the extra 
information about the running jobs to make the example simpler):


```
enum defaultChooser(T) = function size_t(T[] queue) {
 return 0;
};

struct S(T, size_t function(T[]) chooser = defaultChooser!T) {
}

void main() {
 S!int s;
}
```

this fails and I get this:

Error: template instance S!int does not match template declaration 
S(T, ulong function(T[]) chooser = defaultChooser!T)


If instead of returning the index the actual item is returned, it works!

```
enum defaultChooser(T) = function T(T[] queue) {
 return queue[0];
};

struct S(T, T function(T[]) chooser = defaultChooser!T) {
}

void main() {
 S!int s;
}
```

As you can see, the only change is the type the function returns, but I 
don't see how it should make any difference.


Also, changing from "enum" to "static immutable", or even removing the 
"enum" and directly embedding the function literal doesn't seem to make 
any difference.


Any ideas on what might be going on??


Even more strange:

```
enum defaultChooser(T) = function size_t(T[] queue) {
return 0;
};

static assert (is (typeof(defaultChooser!int) == size_t function(int[] 
queue) pure nothrow @nogc @safe));


struct S(T, size_t function(T[] queue) pure nothrow @nogc @safe chooser) {
}

void main() {
S!(int, defaultChooser!int) s;
}
```

The static assert passes (tried with the wrong values), yet I get this 
error message:


Error: template instance S!(int, function ulong(int[] queue) => 0LU) does not match template declaration S(T, ulong function(T[] queue) pure nothrow @nogc @safe chooser) 


Am I missing something fundamental? But then, why does it work if I 
change the return type in the template parameter?


Re: Weird template instantiation problem

2017-06-12 Thread ketmar via Digitalmars-d-learn

more funny compiler messages:

alias xx = size_t function (int[]);
struct S1(T, typeof(xx) X) {}
void main() {
  S1!(int, defaultChooser!int) s;
}

Error: type uint function(int[]) is not an expression

but:

struct S2(T, typeof(defaultChooser!T) chooser=defaultChooser!T) {}
void main() {
  S2!int s;
}

Error: undefined identifier T

error messages are totally random (and why `typeof()` is not allowed there?)


Re: Weird template instantiation problem

2017-06-12 Thread ketmar via Digitalmars-d-learn
p.s.: while i understand the technical reason for second error message, it 
is still random and confusing.


Re: Weird template instantiation problem

2017-06-12 Thread Arafel via Digitalmars-d-learn

On Monday, 12 June 2017 at 19:23:10 UTC, ketmar wrote:
p.s.: while i understand the technical reason for second error 
message, it is still random and confusing.


I think the reason for the typeof problem is that it works with 
expressions, not with types (so, typeof (int) is also not valid), 
and the alias resolves ultimately to a type.


I actually found a workaround for the original issue:

```
enum defaultChooser(T) = function size_t(T[] queue) {
return 0;
};

struct S(T, alias chooser = defaultChooser!int) if 
(is(typeof(chooser) : size_t function(T[]))) {

}

void main() {
S!(int, defaultChooser!int) s;
}
```

This works, but strangely if I try "==" instead of ":" in the 
template condition, then it fails again. Honestly I don't know 
why it makes a difference, I guess attribute inference might be 
at fault... but in the version with the "static assert" I was 
explicitly checking them, and they apparently matched...


Also, this is just a(n ugly) workaround, and there might be side 
effects of using an alias parameter that I'm not aware of... and 
more importantly, I still think the original version should work! 
;-)


Re: Weird template instantiation problem

2017-06-12 Thread ketmar via Digitalmars-d-learn

Arafel wrote:


I actually found a workaround for the original issue:


yeah, sorry for not proposing a workaround: i thought that you already did 
it, and now you're just interested why the original code doesn't work. ;-)


i think that this is a bug (or, rather, unimplemented feature).


Re: Weird template instantiation problem

2017-06-13 Thread Arafel via Digitalmars-d-learn
Well, I had kind of found a workaround (changing the return type to 
return the element and not the index) which I didn't like too much (what 
if there are duplicates?).


Now that I've found a "proper" workaround well, I'm still interested 
in knowing the reason, if possible, or if it's a bug.


On 06/12/2017 09:49 PM, ketmar wrote:
yeah, sorry for not proposing a workaround: i thought that you already 
did it, and now you're just interested why the original code doesn't 
work. ;-)


i think that this is a bug (or, rather, unimplemented feature).




Re: Weird template instantiation problem

2017-06-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/12/17 11:31 AM, Arafel wrote:


As you can see, the only change is the type the function returns, but I
don't see how it should make any difference.

Also, changing from "enum" to "static immutable", or even removing the
"enum" and directly embedding the function literal doesn't seem to make
any difference.

Any ideas on what might be going on??


Looks like a bug to me. Please file.

-Steve


Using attributes inside template instantiation

2014-06-25 Thread Uranuz via Digitalmars-d-learn
I'm trying to declare format for database record in compile time. 
I consider to use attributes fo this. Can I do something similar 
to this code?


struct RecordFormat(T)
{}

alias Format = RecordFormat!( @("cool") int );

pragma( msg, Format );

void main()
{
}

Or I want something strange that is not supported by language? 
For now I don't understand whether UDA are a part of types or 
they are a part of variable instance definition or something 
different (3rd dimension)).


For example 'const int' is a type but what @attribute int is? Can 
it be considered as separate type or it could be binded to 
definition of variable only?

@attribute int number;

I failed to alias type
alias coolInt = @("cool") int;

But I can alias const int
alias constInt = const int;

I think I understood something wrong about attributes.


__traits(compiles) and template instantiation

2016-04-07 Thread jmh530 via Digitalmars-d-learn
I've been playing around with __traits and I find myself confused 
on one aspect. In the code below, I was testing whether some 
templates would compile given types. For the most part it works 
as I would expect.


I think I get why the third one works with foo!(int). My guess is 
that it assumed that U is the same as T and both are int. 
However, that wouldn't make sense with the last one where I use 
bar!(int). In that one it's basically ignoring the second 
template constraint. So I don't understand what's going on for 
that last line to compile. To confirm I wasn't crazy, I get an 
error with

alias bar_ = bar!(int);



import std.traits : isNumeric;
import std.range : isInputRange;

void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { }

void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { }

void main()
{
assert(__traits(compiles, foo!(int, int))); //I get this
assert(!__traits(compiles, foo!(bool, bool)));  //I get this
assert(__traits(compiles, foo!(int)));  //I think I get this
assert(__traits(compiles, bar!(int, int[])));   //I get this
assert(!__traits(compiles, bar!(int, int)));//I get this
assert(__traits(compiles, bar!(int)));  //I don't get this
}


Re: Reporting unsupported template instantiation

2010-08-04 Thread BCS

Hello Kagamin,


http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmar
s.D&article_id=114518

Is there a way to report a custom error message for unsupported
template instantiations?



template Foo(T)
{
   static assert(Chcek!(T), "message");
  ...
}

template Bar(T) if (is( T == U))
{
  ...
}

template Bar(T) { static assert(false, "message"); }

--
... <





Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


If symName is always a string literal, then you don't need to 
append a "\0"; string literals always have a trailing NUL after 
them, and they autoconvert to const(char)[] so you don't need the 
.ptr either.


Re: 0 cost template instantiation

2021-09-29 Thread Basile B. via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


The main problem is that this function is costing 2KB per 
instantiation, which is something pretty high. Specially if I 
inline, there is almost no cost when compared to its inline 
version. Trying to use pragma(inline, true) didn't do anything 
too.


cant you just use a regular functions ? loading happens at 
runtime right ?


Re: 0 cost template instantiation

2021-09-29 Thread Hipreme via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:56:42 UTC, Basile B. wrote:

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


The main problem is that this function is costing 2KB per 
instantiation, which is something pretty high. Specially if I 
inline, there is almost no cost when compared to its inline 
version. Trying to use pragma(inline, true) didn't do anything 
too.


cant you just use a regular functions ? loading happens at 
runtime right ?



The entire reason to having that function is having that syntax 
which would pretty much do the monkey's job for me:


Instead of writing

myFunction = cast(typeof(myFunction))_loadSymbol(_dll, 
"myFunction");


I could write

loadSymbol!myFunction;

But if no other way is found of doing that, I will do the massive 
rewriting.


Anyway, I don't think the problem is not in the way I'm doing, 
but the output, as that template could easily be inlined


Re: 0 cost template instantiation

2021-09-29 Thread Basile B. via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:02:19 UTC, Hipreme wrote:

On Thursday, 30 September 2021 at 01:56:42 UTC, Basile B. wrote:

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a 
symbol, it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


The main problem is that this function is costing 2KB per 
instantiation, which is something pretty high. Specially if I 
inline, there is almost no cost when compared to its inline 
version. Trying to use pragma(inline, true) didn't do 
anything too.


cant you just use a regular functions ? loading happens at 
runtime right ?



The entire reason to having that function is having that syntax 
which would pretty much do the monkey's job for me:


Instead of writing

myFunction = cast(typeof(myFunction))_loadSymbol(_dll, 
"myFunction");


I could write

loadSymbol!myFunction;

But if no other way is found of doing that, I will do the 
massive rewriting.


Anyway, I don't think the problem is not in the way I'm doing, 
but the output, as that template could easily be inlined


well ok. Maybe try to see if overloads

  void loadSymbol(alias s)()
  void loadSymbol(alias s, string symName)()

helps. That save the static if. In addition there's the null 
sentinel that can save a bit of memory, as you've been suggested.


Re: 0 cost template instantiation

2021-09-29 Thread Hipreme via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


The main problem is that this function is costing 2KB per 
instantiation, which is something pretty high. Specially if I 
inline, there is almost no cost when compared to its inline 
version. Trying to use pragma(inline, true) didn't do anything 
too.


If I understood correctly, mixin template would be some way to 
actually inline anything. The problem is that I can't have any 
kind of expression inside it, so, that's the only way I could 
think in how to do it.


Optimization seems to don't take care of that behaviour too.

I would like to know which approach could I take for making 
something like C's #define for that.


As this function could be really rewritten as a macro if I were 
coding in C, the cost is too high for a function that would be 
only a syntactic sugar





I could reduce by almost 100kb of code by instead of using the 
former option, I use:


```
void loadSymbols(Ts...)()
{
static foreach(s; Ts)
s = cast(typeof(s))_loadSymbol(_dll, s.stringof);
}
```

Then instead of making a call for each one, I just pass a list of 
templates, this would only create one instantiation per need.


I do still don't think that this should be the answer, as the 
alias problem is not yet  solved. It takes a lot of size for 
functions that could be only syntactic sugar, where C would be a 
lot better





Re: 0 cost template instantiation

2021-09-29 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:02:19 UTC, Hipreme wrote:

Instead of writing

myFunction = cast(typeof(myFunction))_loadSymbol(_dll, 
"myFunction");


I could write

loadSymbol!myFunction;

But if no other way is found of doing that, I will do the 
massive rewriting.


---

void function() x;

void load(void* thing, string name) {
   // this lhs cast is the magic, the rhs cast unneeded in 
reality cuz GetProcAddress returns void* naturally

* cast(void**) thing = cast(void*) 0xdeadbeef;
}

void main() {
// no cast here but yes repeated name
load(&x, "foo");

 // casts needed here just to do the comparison
assert(cast(void*) x == cast(void*) 0xdeadbeef);
}

---


A little void casting inside the function can do the trick. You 
will have to pass the name separately though.



im off to bed ttyl


Re: 0 cost template instantiation

2021-09-29 Thread Adam D Ruppe via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:09:50 UTC, Hipreme wrote:
I could reduce by almost 100kb of code by instead of using the 
former option, I use:


yes this is what id o you can list the Ts in an interface too. 
see my simpledisplay.d `interface GL` for example



I do still don't think that this should be the answer, as the 
alias problem is not yet  solved. It takes a lot of size for 
functions that could be only syntactic sugar, where C would be 
a lot better


well it must generate functions for each thing there by 
definition and since you call them at runtime it can't cut them 
out either. so this is kinda meh


you MIGHT  be able to do a tempalte that forwards to a single 
runtime function though. but i seriously need to g2g maybe can 
look tomorrow


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 01:44:57 UTC, jfondren wrote:

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a symbol, 
it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


If symName is always a string literal, then you don't need to 
append a "\0"; string literals always have a trailing NUL after 
them, and they autoconvert to const(char)[] so you don't need 
the .ptr either.


Playing around with this, with a mock-up of your code, doesn't 
change object size at all.


Is the actual source available, that you're seeing this with?


Re: 0 cost template instantiation

2021-09-29 Thread Hipreme via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:22:35 UTC, jfondren wrote:

On Thursday, 30 September 2021 at 01:44:57 UTC, jfondren wrote:

On Thursday, 30 September 2021 at 01:09:47 UTC, Hipreme wrote:
I have a template function that all it does is given a 
symbol, it loads a dll for its type + its name:


```
void loadSymbol(alias s, string symName = "")()
{
static if(symName == "")
s = cast(typeof(s))_loadSymbol(_dll, (s.stringof~"\0").ptr);
else
s = cast(typeof(s))_loadSymbol(_dll, (symName~"\0").ptr);
}
```


If symName is always a string literal, then you don't need to 
append a "\0"; string literals always have a trailing NUL 
after them, and they autoconvert to const(char)[] so you don't 
need the .ptr either.


Playing around with this, with a mock-up of your code, doesn't 
change object size at all.


Is the actual source available, that you're seeing this with?


https://github.com/MrcSnm/HipremeEngine/tree/hotload/api

You may try messing at the module api.graphics.g2d.renderer2d

There is a function called initG2D

Try changing it from loadSymbols to each one loadSymbol.

You can just dub at the folder api.





Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 02:31:50 UTC, Hipreme wrote:

https://github.com/MrcSnm/HipremeEngine/tree/hotload/api

You may try messing at the module api.graphics.g2d.renderer2d

There is a function called initG2D

Try changing it from loadSymbols to each one loadSymbol.

You can just dub at the folder api.


The version I checked out, 2874073b54, doesn't have a loadSymbols.

As provided, loadSymbol without the "static if":

965K libhipengine_api.a

with `mixin(loadSymbol("name"))` instead of a template:

749K libhipengine_api.a

https://gist.github.com/jrfondren/d776ccffb105f464b53c53712656a1d3

That's probably disappointing, since it's a much less pleasant 
interface, but what you could do is take the both entire 
`extern(C) void function() beginSprite; ... 
loadSymbol!beginSprite;` blocks and put them in one string 
literal that you process with a function and mixin once. Now 
instead of an annoying macro alternative you have a DSL for 
DLL-extern functions.


Re: 0 cost template instantiation

2021-09-29 Thread jfondren via Digitalmars-d-learn

On Thursday, 30 September 2021 at 03:13:28 UTC, jfondren wrote:

As provided, loadSymbol without the "static if":

965K libhipengine_api.a

with `mixin(loadSymbol("name"))` instead of a template:

749K libhipengine_api.a


The difference goes down to 66K vs. 60K with `dub -brelease 
--compiler=gdc`. ldc's not as slim but still much better than 
dmd, and -brelease is actually much less significant. So dmd's 
the main culprit for the bloat here. huh.


But since you have importPaths-ldc perhaps you weren't using dmd 
to begin with.


Re: 0 cost template instantiation

2021-09-29 Thread Hipreme via Digitalmars-d-learn

On Thursday, 30 September 2021 at 03:21:51 UTC, jfondren wrote:

On Thursday, 30 September 2021 at 03:13:28 UTC, jfondren wrote:

As provided, loadSymbol without the "static if":

965K libhipengine_api.a

with `mixin(loadSymbol("name"))` instead of a template:

749K libhipengine_api.a


The difference goes down to 66K vs. 60K with `dub -brelease 
--compiler=gdc`. ldc's not as slim but still much better than 
dmd, and -brelease is actually much less significant. So dmd's 
the main culprit for the bloat here. huh.


But since you have importPaths-ldc perhaps you weren't using 
dmd to begin with.



Yup. The mixin(loadSymbol("")) seems the best way to do.

I believe that should be the option for loading separated symbols 
while loadSymbols version is the best for loading a lot of 
symbols(IDK how expensive is mixing a lot of functions) as it 
costs 1KB per instantiation.


I'm actually using DMD and LDC, dmd compiles a bit faster, but I 
use ldc for deploying it. Never used GDC.






Re: Weird template instantiation speed?

2023-07-09 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/9/23 7:54 AM, IchorDev wrote:
While working on some new bindings, I've discovered that if `opAssign` 
in a struct template "`BindingTempl(T)`" has the return type 
"`BindingTempl!T` then it adds about 4 seconds to the compile time per 
instantiation of `BindingTempl`. The added compile time is much lower if 
a function other than `opAssign` returns `BindingTempl!T`. Is opAssign a 
particularly bad operator to overload in templates or something?


This is probably a bug somewhere, 4 seconds is too much. A reduced test 
case would be helpful.


But I wanted to note, inside a struct template, the template name (by 
itself) is equivalent to the current instantiation. So just returning 
`BindingTempl` would be equivalent, and might not trigger this problem.


See if that helps.

-Steve


Re: Weird template instantiation speed?

2023-07-09 Thread IchorDev via Digitalmars-d-learn
On Sunday, 9 July 2023 at 14:49:39 UTC, Steven Schveighoffer 
wrote:


This is probably a bug somewhere, 4 seconds is too much. A 
reduced test case would be helpful.


But I wanted to note, inside a struct template, the template 
name (by itself) is equivalent to the current instantiation. So 
just returning `BindingTempl` would be equivalent, and might 
not trigger this problem.


See if that helps.

-Steve


Thank you for letting me know about being able to use 
`BindingTempl`, I had no idea! Unfortunately it doesn't mitigate 
the compile times, though.
I forgot to mention, it only happens when specifying `-O` with 
DMD. LDC and GDC compile the same thing almost instantly.
Boiling it down to a simple test is tough. If you remove a lot of 
components the struct template depends on then the compile time 
is too fast for anything to be noticeable. I think the issue is 
some kind of snowball-effect.


If anyone wants to try to reproduce this issue:
1. Download [this exact 
commit](https://github.com/ichordev/bindbc-imgui/tree/65d02d68e4188250c948147a04a5820de3479a44) of the WIP BindBC-ImGui repo. (the newer commits won't compile)
2. Edit dub.selections.json to change `"bindbc-common"`'s version 
to `"0.0.6"`.

3. Run:
```
dmd -extern-std=c++11 -lib -O -version=BindImGui_Static -Isource/ 
-I~/.dub/packages/bindbc-common/0.0.6/bindbc-common/source/ 
source/bindbc/imgui/config.d source/bindbc/imgui/package.d 
source/imgui/impl.d source/imgui/package.d -v

```

4. Now, remove `-O` from the dmd command. Blink and you'll miss 
it compiling!


Re: template instantiation --- having trouble therewith

2013-09-03 Thread John Colvin
On Tuesday, 3 September 2013 at 03:49:52 UTC, Carl Sturtivant 
wrote:


template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

Dptr!(T,U) muddle( T, U...)( Dptr!(T,U) f) {
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


The above technique seemed natural to me, but I get this 
message from dmd:


p1.d(15): Error: template p1.muddle does not match any function 
template declaration. Candidates are:

p1.d(7):p1.muddle(T, U...)(Dptr!(T, U) f)
p1.d(15): Error: template p1.muddle(T, U...)(Dptr!(T, U) f) 
cannot deduce template function from argument types !()(int 
delegate(int))


and if I use muddle!(int,int) instead it doesn't help. This is 
likely a misunderstanding on my part --- please show me how to 
sort this out.


I'm confused as to what you're trying to do... your example code 
is equivalent to


  import std.stdio;
  int x = 3;
  int scale( int s) { return x * s; }
  auto f = &scale;
  writeln( f(7) );


Re: template instantiation --- having trouble therewith

2013-09-03 Thread Carl Sturtivant


I'm confused as to what you're trying to do... your example 
code is equivalent to


  import std.stdio;
  int x = 3;
  int scale( int s) { return x * s; }
  auto f = &scale;
  writeln( f(7) );


No it isn't according to dmd.

My code is a minimal piece that produces the same error as some 
real code. The higher order generic function muddle in the real 
code is supposed to transform one delegate into another, but I 
still get the template problem if muddle is the identity function 
(given here).


My example code isn't equivalent to the above according to the 
compiler. Why is that? And how can I make it work?


Re: template instantiation --- having trouble therewith

2013-09-03 Thread Manfred Nowak
Carl Sturtivant wrote:

> No it isn't according to dmd.
dmd does not express this.

according to
> p1.d(15): Error: [...]
dmd "cannot deduce" that `Dptr!(T, U)' might be equal to
`int delegate(int)'

-manfred




Re: template instantiation --- having trouble therewith

2013-09-03 Thread Manfred Nowak
Carl Sturtivant wrote:
> How do I fix this?

maybe it is currently not fixable because of restrictions in the deduction 
algorithm.

Obviously the deduction works if the instantion of the template is replaced 
by a symbol by `alias T delegate( U) Dptr;' or similar.

-manfred





Re: template instantiation --- having trouble therewith

2013-09-03 Thread Carl Sturtivant

On Tuesday, 3 September 2013 at 13:42:44 UTC, Manfred Nowak wrote:

Carl Sturtivant wrote:


No it isn't according to dmd.

dmd does not express this.

according to

p1.d(15): Error: [...]

dmd "cannot deduce" that `Dptr!(T, U)' might be equal to
`int delegate(int)'

-manfred


I understood that. How do I fix this? Writing muddle!(int,int) in
the unit test so there's no type inference needed gives the same 
error message.


Re: template instantiation --- having trouble therewith

2013-09-03 Thread Manfred Nowak
Carl Sturtivant wrote:
> Writing muddle!(int,int)
[...]
> gives the same error message.

Not entirely true:

template muddle( T, U...){
  alias T delegate( U) Dptr; 
  auto muddle1( T, U...)( Dptr f) {
return f; //or make another delegate in real code
  }
  alias muddle1!( T, U) muddle;
}

unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f= muddle!( int, int)( &scale);
writeln( f(7));
}

-manfred


Re: template instantiation --- having trouble therewith

2013-09-03 Thread Manfred Nowak
Carl Sturtivant wrote:
> is supposed to transform one delegate into another

Then please declare the template parameters to be delegates:

U muddle( T, U)( T f) {
uint g( int fp){
return cast(uint)( 5* f( fp));
}
auto gP= &g;
return gP;
}

unittest {
 import std.stdio;
  int x = 3;
int scale( int s) { return x * s; }
  auto f= muddle!( int delegate( int), uint delegate( int))( &scale);
writeln( f(7));
}
// no deduction problems

-manfred


Re: template instantiation --- having trouble therewith

2013-09-04 Thread Carl Sturtivant

On Tuesday, 3 September 2013 at 17:25:12 UTC, Manfred Nowak wrote:

Carl Sturtivant wrote:

Writing muddle!(int,int)

[...]

gives the same error message.


Not entirely true:

template muddle( T, U...){
  alias T delegate( U) Dptr;
  auto muddle1( T, U...)( Dptr f) {
return f; //or make another delegate in real code
  }
  alias muddle1!( T, U) muddle;
}

unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f= muddle!( int, int)( &scale);
writeln( f(7));
}


Can you point me at some documentation that explains this 
behavior?





Re: template instantiation --- having trouble therewith

2013-09-04 Thread Carl Sturtivant

On Tuesday, 3 September 2013 at 13:42:44 UTC, Manfred Nowak wrote:

Carl Sturtivant wrote:


No it isn't according to dmd.

dmd does not express this.

according to

p1.d(15): Error: [...]

dmd "cannot deduce" that `Dptr!(T, U)' might be equal to
`int delegate(int)'


Indeed, dmd doesn't know the equivalence, and therefore won't 
compile my code.


Re: template instantiation --- having trouble therewith

2013-09-04 Thread Carl Sturtivant

On Tuesday, 3 September 2013 at 21:52:58 UTC, Manfred Nowak wrote:

Carl Sturtivant wrote:

is supposed to transform one delegate into another


Then please declare the template parameters to be delegates:

U muddle( T, U)( T f) {
uint g( int fp){
return cast(uint)( 5* f( fp));
}
auto gP= &g;
return gP;
}

unittest {
 import std.stdio;
  int x = 3;
int scale( int s) { return x * s; }
	  auto f= muddle!( int delegate( int), uint delegate( int))( 
&scale);

writeln( f(7));
}


But I want some inference. In the real code the relevant 
delegates will have lots of long messy signatures that have 
already been declared.


And in your example above, I want the arguments of the delegates 
in general to be a type tuple, because any delegate may be passed.





Re: template instantiation --- having trouble therewith

2013-09-04 Thread Carl Sturtivant

On Tuesday, 3 September 2013 at 17:25:12 UTC, Manfred Nowak wrote:

Carl Sturtivant wrote:

Writing muddle!(int,int)

[...]

gives the same error message.


Not entirely true:

template muddle( T, U...){
  alias T delegate( U) Dptr;
  auto muddle1( T, U...)( Dptr f) {
return f; //or make another delegate in real code
  }
  alias muddle1!( T, U) muddle;
}

unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f= muddle!( int, int)( &scale);
writeln( f(7));
}

-manfred


This technique does what I want if there's a single parameter to 
the delegate. I'll explore from here; thanks for all the examples.


Carl.



Re: template instantiation --- having trouble therewith

2013-09-05 Thread John Colvin
On Tuesday, 3 September 2013 at 11:51:37 UTC, Carl Sturtivant 
wrote:


I'm confused as to what you're trying to do... your example 
code is equivalent to


 import std.stdio;
 int x = 3;
 int scale( int s) { return x * s; }
 auto f = &scale;
 writeln( f(7) );


No it isn't according to dmd.

My code is a minimal piece that produces the same error as some 
real code. The higher order generic function muddle in the real 
code is supposed to transform one delegate into another, but I 
still get the template problem if muddle is the identity 
function (given here).


My example code isn't equivalent to the above according to the 
compiler. Why is that? And how can I make it work?


Ok, that makes more sense.

The reason why it doesn't work is that you're effectively asking 
the compiler to work backwards from {the type of the delegate 
passed to muddle} to {the type parameters that would have to be 
used in Dptr to generate that delegate type}.
I'm no expert on type-deduction algorithms, but I seriously doubt 
that's a solvable problem in the general case, especially 
considering that the definition of Dptr could contain string 
mixins etc.   In the general case, all code is forwards-only.


Anyhow, it's easy to work around:

import std.traits : ReturnType, ParameterTypeTuple;

template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

auto muddle( DT)( DT f) {
alias T = ReturnType!f;
alias U = ParameterTypeTuple!f;
//use T and U
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


Re: template instantiation --- having trouble therewith

2013-09-05 Thread John Colvin

On Thursday, 5 September 2013 at 09:00:27 UTC, John Colvin wrote:
On Tuesday, 3 September 2013 at 11:51:37 UTC, Carl Sturtivant 
wrote:


I'm confused as to what you're trying to do... your example 
code is equivalent to


import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f = &scale;
writeln( f(7) );


No it isn't according to dmd.

My code is a minimal piece that produces the same error as 
some real code. The higher order generic function muddle in 
the real code is supposed to transform one delegate into 
another, but I still get the template problem if muddle is the 
identity function (given here).


My example code isn't equivalent to the above according to the 
compiler. Why is that? And how can I make it work?


Ok, that makes more sense.

The reason why it doesn't work is that you're effectively 
asking the compiler to work backwards from {the type of the 
delegate passed to muddle} to {the type parameters that would 
have to be used in Dptr to generate that delegate type}.
I'm no expert on type-deduction algorithms, but I seriously 
doubt that's a solvable problem in the general case, especially 
considering that the definition of Dptr could contain string 
mixins etc.   In the general case, all code is forwards-only.


Anyhow, it's easy to work around:

import std.traits : ReturnType, ParameterTypeTuple;

template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

auto muddle( DT)( DT f) {
alias T = ReturnType!f;
alias U = ParameterTypeTuple!f;
//use T and U
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


Having said that, in the case where you explicitly set the 
template parameters to muddle I think it *should* work and is 
probably a bug (or at least a simple enhancement) that it doesn't.


Re: template instantiation --- having trouble therewith

2013-09-05 Thread John Colvin

On Thursday, 5 September 2013 at 09:11:06 UTC, John Colvin wrote:
On Thursday, 5 September 2013 at 09:00:27 UTC, John Colvin 
wrote:
On Tuesday, 3 September 2013 at 11:51:37 UTC, Carl Sturtivant 
wrote:


I'm confused as to what you're trying to do... your example 
code is equivalent to


import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f = &scale;
writeln( f(7) );


No it isn't according to dmd.

My code is a minimal piece that produces the same error as 
some real code. The higher order generic function muddle in 
the real code is supposed to transform one delegate into 
another, but I still get the template problem if muddle is 
the identity function (given here).


My example code isn't equivalent to the above according to 
the compiler. Why is that? And how can I make it work?


Ok, that makes more sense.

The reason why it doesn't work is that you're effectively 
asking the compiler to work backwards from {the type of the 
delegate passed to muddle} to {the type parameters that would 
have to be used in Dptr to generate that delegate type}.
I'm no expert on type-deduction algorithms, but I seriously 
doubt that's a solvable problem in the general case, 
especially considering that the definition of Dptr could 
contain string mixins etc.   In the general case, all code is 
forwards-only.


Anyhow, it's easy to work around:

import std.traits : ReturnType, ParameterTypeTuple;

template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

auto muddle( DT)( DT f) {
alias T = ReturnType!f;
alias U = ParameterTypeTuple!f;
//use T and U
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


Having said that, in the case where you explicitly set the 
template parameters to muddle I think it *should* work and is 
probably a bug (or at least a simple enhancement) that it 
doesn't.


I filed a bug report for it
http://d.puremagic.com/issues/show_bug.cgi?id=10969


Re: template instantiation --- having trouble therewith

2013-09-05 Thread John Colvin

On Thursday, 5 September 2013 at 09:33:00 UTC, John Colvin wrote:
On Thursday, 5 September 2013 at 09:11:06 UTC, John Colvin 
wrote:
On Thursday, 5 September 2013 at 09:00:27 UTC, John Colvin 
wrote:
On Tuesday, 3 September 2013 at 11:51:37 UTC, Carl Sturtivant 
wrote:


I'm confused as to what you're trying to do... your example 
code is equivalent to


import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
auto f = &scale;
writeln( f(7) );


No it isn't according to dmd.

My code is a minimal piece that produces the same error as 
some real code. The higher order generic function muddle in 
the real code is supposed to transform one delegate into 
another, but I still get the template problem if muddle is 
the identity function (given here).


My example code isn't equivalent to the above according to 
the compiler. Why is that? And how can I make it work?


Ok, that makes more sense.

The reason why it doesn't work is that you're effectively 
asking the compiler to work backwards from {the type of the 
delegate passed to muddle} to {the type parameters that would 
have to be used in Dptr to generate that delegate type}.
I'm no expert on type-deduction algorithms, but I seriously 
doubt that's a solvable problem in the general case, 
especially considering that the definition of Dptr could 
contain string mixins etc.   In the general case, all code is 
forwards-only.


Anyhow, it's easy to work around:

import std.traits : ReturnType, ParameterTypeTuple;

template Dptr( T, U...) {
alias T delegate( U args) Dptr;
}

auto muddle( DT)( DT f) {
alias T = ReturnType!f;
alias U = ParameterTypeTuple!f;
//use T and U
return f; //or make another delegate in real code
}


unittest {
import std.stdio;
int x = 3;
int scale( int s) { return x * s; }
Dptr!(int,int) f = muddle( &scale);
writeln( f(7));
}


Having said that, in the case where you explicitly set the 
template parameters to muddle I think it *should* work and is 
probably a bug (or at least a simple enhancement) that it 
doesn't.


I filed a bug report for it
http://d.puremagic.com/issues/show_bug.cgi?id=10969


and only 26.5 mins after posting the bug, there's a pull request 
to fix it: https://github.com/D-Programming-Language/dmd/pull/2526


That's what I call service :p


Re: Using attributes inside template instantiation

2014-06-25 Thread Chris Nicholson-Sauls via Digitalmars-d-learn
UDA's are compile-time metadata associated with a specific 
declaration.  So in something like:


@foo int x;

The @foo is attached to x, but is not part of the type.


Re: Using attributes inside template instantiation

2014-06-25 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jun 25, 2014 at 05:10:06PM +, Chris Nicholson-Sauls via 
Digitalmars-d-learn wrote:
> UDA's are compile-time metadata associated with a specific
> declaration.  So in something like:
> 
> @foo int x;
> 
> The @foo is attached to x, but is not part of the type.

The term "attribute" is a bit confusing, especially since "property" is
also used in the language to refer to something completely different. A
better term is perhaps "annotation". The @foo is an annotation on x, but
its type is just int. Furthermore, the @foo annotation on it only exists
at compile-type; it doesn't exist at runtime. The purpose is really to
enhance compile-time introspection and metaprogramming; but what the OP
wants seems to be something else altogether.

Sadly, the "attribute" terminology has stuck, and is unlikely to change.


T

-- 
What do you get if you drop a piano down a mineshaft? A flat minor.


Re: Using attributes inside template instantiation

2014-06-25 Thread Chris Nicholson-Sauls via Digitalmars-d-learn
On Wednesday, 25 June 2014 at 17:21:21 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:


The term "attribute" is a bit confusing, especially since 
"property" is
also used in the language to refer to something completely 
different. A
better term is perhaps "annotation". The @foo is an annotation 
on x, but

its type is just int.


Agree whole-heartedly.  I usually introduce people to the idea by 
referring to them as annotations, which they understand quickly, 
then later tell them that it's called an attribute because of 
reasons no one knows.  I get funny looks, but at least they 
comprehend it.  I'm not so sure it's too late to get the 
terminology changed, though, and I sincerely hope it will.


Re: Using attributes inside template instantiation

2014-06-26 Thread Uranuz via Digitalmars-d-learn

But if I write

@("hello") struct Hello {}

so all of the variables that have type Hello will have attribute 
@("hello") like come type qualifier because attribute is a part 
of declaration of Hello. Do I understand correctly?


Re: Using attributes inside template instantiation

2014-06-26 Thread Meta via Digitalmars-d-learn

On Thursday, 26 June 2014 at 07:11:03 UTC, Uranuz wrote:

But if I write

@("hello") struct Hello {}

so all of the variables that have type Hello will have 
attribute @("hello") like come type qualifier because attribute 
is a part of declaration of Hello. Do I understand correctly?


No, it is only the symbol Hello that will have the attribute 
@("hello"). Attributes are attached to symbols, not types or 
values.


Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread jmh530 via Digitalmars-d-learn
When using a template with multiple functions within it, is it 
possible to access the underlying functions directly? Not sure I 
am missing anything, but what works when the functions are named 
differently from the headline template doesn't work when the 
functions are named the same.


import std.stdio: writeln;
import std.traits: isFunction;

template foo(T) {
void foo(U)(U x) {
writeln("here0");
}

void foo(U, V)(U x, V y) {
writeln("there0");
}
}

template bar(T) {
void baz(U)(U x) {
writeln("here1");
}

void baz(U, V)(U x, V y) {
writeln("there1");
}
}

void foobar(T)(T x) {}

void main() {
foo!int.foo!(float, double)(1f, 2.0); //Error: template 
foo(U)(U x) does not have property foo
writeln(isFunction!(foo!int)); //prints false, as expected 
b/c not smart enough to look through
writeln(isFunction!(foo!int.foo!float)); //Error: template 
identifier foo is not a member of template 
onlineapp.foo!int.foo(U)(U x)

writeln(isFunction!(foo!int.foo!(float, double))); //ditto

bar!int.baz!(float, double)(1f, 2.0); //prints there1
writeln(isFunction!(bar!int.baz!(float, double))); //prints 
true


writeln(isFunction!(foobar!int)); //prints true
}




Re: __traits(compiles) and template instantiation

2016-04-07 Thread Alex Parrill via Digitalmars-d-learn

On Thursday, 7 April 2016 at 20:31:12 UTC, jmh530 wrote:
I've been playing around with __traits and I find myself 
confused on one aspect. In the code below, I was testing 
whether some templates would compile given types. For the most 
part it works as I would expect.


I think I get why the third one works with foo!(int). My guess 
is that it assumed that U is the same as T and both are int. 
However, that wouldn't make sense with the last one where I use 
bar!(int). In that one it's basically ignoring the second 
template constraint. So I don't understand what's going on for 
that last line to compile. To confirm I wasn't crazy, I get an 
error with

alias bar_ = bar!(int);



import std.traits : isNumeric;
import std.range : isInputRange;

void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { }

void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { }

void main()
{
assert(__traits(compiles, foo!(int, int))); //I get this
assert(!__traits(compiles, foo!(bool, bool)));  //I get this
assert(__traits(compiles, foo!(int)));  //I think I get this
assert(__traits(compiles, bar!(int, int[])));   //I get this
assert(!__traits(compiles, bar!(int, int)));//I get this
assert(__traits(compiles, bar!(int)));  //I don't get this
}


Neither the third nor sixth lines should be true.

alias wrongfoo = foo!int; /* Error: template instance foo!int 
does not match template declaration foo(T, U)(T x, U y) if 
(isNumeric!T && isNumeric!U) */

alias rightfoo = foo!(int, int); /* ok */

File a DMD bug.

(Also, you can use static assert here to check the assertions at 
build-time instead of run-time)


Re: __traits(compiles) and template instantiation

2016-04-07 Thread jkpl via Digitalmars-d-learn

On Thursday, 7 April 2016 at 21:36:37 UTC, Alex Parrill wrote:

On Thursday, 7 April 2016 at 20:31:12 UTC, jmh530 wrote:
I've been playing around with __traits and I find myself 
confused on one aspect. In the code below, I was testing 
whether some templates would compile given types. For the most 
part it works as I would expect.

[...]

Neither the third nor sixth lines should be true.

alias wrongfoo = foo!int; /* Error: template instance 
foo!int does not match template declaration foo(T, U)(T x, U y) 
if (isNumeric!T && isNumeric!U) */

alias rightfoo = foo!(int, int); /* ok */

File a DMD bug.

(Also, you can use static assert here to check the assertions 
at build-time instead of run-time)


is(typeof()) gives the expected results:

import std.traits : isNumeric;
import std.range : isInputRange;

void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { }

void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { }

unittest
{
static assert(is(typeof(foo!(int, int;  //I get this
static assert(!is(typeof(foo!(bool, bool;   //I get this
static assert(!is(typeof(foo!(int;  //I think I get this
static assert(is(typeof(bar!(int, int[];//I get this
static assert(!is(typeof(bar!(int, int; //I get this
static assert(!is(typeof(bar!(int;  //I don't get this
}

(note well I have changed the assertion 3 and 6).

There must be a subtle difference between __traits(compile,...) 
and is(typeof()).
Does "compiles" mean that you've get something but that this 
thing is not always of a valid type ?


Re: __traits(compiles) and template instantiation

2016-04-08 Thread jmh530 via Digitalmars-d-learn
It looks like the bug has already been reported. There are a few 
associated with __traits(compiles), but this one seems most 
relevant:

https://issues.dlang.org/show_bug.cgi?id=3448

It also suggests that this is relevant:
https://issues.dlang.org/show_bug.cgi?id=965


Template instantiation and string vs const char[]

2014-09-02 Thread Jason den Dulk via Digitalmars-d-learn

I have this piece of code:


template somet(R...) {
  static if (R.length)
  {
string somet = "[\n"~R[0]~"\n" ~ somet!(R[1..R.length]) ~ 
"]\n";

  }
  else
string somet = "";
}


void main()
{
  writeln(somet!("name","tame"));
  writeln(somet!"name");
}

When I compile it, it generates the error message "static 
variable somet cannot be read at compile time". When I replace 
'string' with 'const char[]', it works.


Can anyone explain why this happens?

Thanks.
Regards


Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread Steven Schveighoffer via Digitalmars-d-learn

On 4/27/20 1:19 PM, jmh530 wrote:
When using a template with multiple functions within it, is it possible 
to access the underlying functions directly? Not sure I am missing 
anything, but what works when the functions are named differently from 
the headline template doesn't work when the functions are named the same.


import std.stdio: writeln;
import std.traits: isFunction;

template foo(T) {
     void foo(U)(U x) {
     writeln("here0");
     }

     void foo(U, V)(U x, V y) {
     writeln("there0");
     }
}

template bar(T) {
     void baz(U)(U x) {
     writeln("here1");
     }

     void baz(U, V)(U x, V y) {
     writeln("there1");
     }
}

void foobar(T)(T x) {}

void main() {
     foo!int.foo!(float, double)(1f, 2.0); //Error: template foo(U)(U x) 
does not have property foo


foo!int aliases to the template foo's inside, so you are already in there.

In reality, you should want to use foo!int!(float, double), but that 
does not parse.


You can do:

alias x = foo!int;
x!(float, double)(...)

or you can just use IFTI:

foo!int(1f, 2.0);

     writeln(isFunction!(foo!int)); //prints false, as expected b/c not 
smart enough to look through


No, because the template hasn't been instantiated. Note that 
isFunction!(foobar) prints false also.


     writeln(isFunction!(foo!int.foo!float)); //Error: template 
identifier foo is not a member of template onlineapp.foo!int.foo(U)(U x)


An eponymous template is equivalent to the members that have the same 
name. There is no way to access the template namespace (this was changed 
some time ago).


with x definition above:

writeln(isFunction!(x!float)); // true


     writeln(isFunction!(foo!int.foo!(float, double))); //ditto

     bar!int.baz!(float, double)(1f, 2.0); //prints there1
     writeln(isFunction!(bar!int.baz!(float, double))); //prints true

     writeln(isFunction!(foobar!int)); //prints true
}




Generally it's just fine to do foo(T, U, V) and dispense with the double 
templates, as IFTI will take care of the other two.


The main reason to have nested templates is when you need to bind the 
explicit template parameters to a variadic, and the IFTI parameters to 
something else.


i.e.:

template foo(T...)
{
void foo(U...)(U args) {... }
}

foo!(int, char, bool)(1, 2, 3) -> foo!(int, char, bool)!(int, int, 
int)(1, 2, 3);


I hope this clears it up a bit.

-Steve


Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Apr 27, 2020 at 05:19:35PM +, jmh530 via Digitalmars-d-learn wrote:
> When using a template with multiple functions within it, is it
> possible to access the underlying functions directly?

Yes, but only if the template is not eponymous.


> Not sure I am missing anything, but what works when the functions are
> named differently from the headline template doesn't work when the
> functions are named the same.

Yes, when the template is eponymous, the name of the template becomes
the name of the eponymous member, and thus effectively hides the other
members from outside access.

This is actually useful when you want to write a template function with
internal implementation details that outside code cannot access no
matter what.  It's like a little encapsulation unit locked away behind
the public-facing eponymous member. I've used this on a few occasions
when I wanted template implementation details to be invisible even to
other code inside the same module.

(Interesting note: you can even stick unittests inside the template
block to test internal details, while still keeping said details away
from prying eyes in the rest of the module. :-P)


T

-- 
Doubtless it is a good thing to have an open mind, but a truly open mind should 
be open at both ends, like the food-pipe, with the capacity for excretion as 
well as absorption. -- Northrop Frye


Re: Implicit Function Template Instantiation (IFTI) Question

2020-04-27 Thread jmh530 via Digitalmars-d-learn
On Monday, 27 April 2020 at 17:40:06 UTC, Steven Schveighoffer 
wrote:

[snip]


Thanks for that. Very detailed.

In terms of a use case, we just added a center function to mir 
[1]. It can take an alias to a function. I wanted to add a check 
that the arity of the function was 1, but it turned out that I 
couldn't do that for mean [2] because it has a similar structure 
as what I posted and arity relies on isCallable, which depends on 
isFunction.



[1] http://mir-algorithm.libmir.org/mir_math_stat.html#.center
[2] http://mir-algorithm.libmir.org/mir_math_stat.html#.mean



Shared, ref, arrays, and reserve template instantiation

2018-09-12 Thread James Blachly via Digitalmars-d-learn
When I add the "shared" attribute to an array, I am no longer 
able to call reserve because the template won't instantiate:


Error: template object.reserve cannot deduce function from 
argument types !()(shared(int[]), int), candidates are:
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4091):  
  object.reserve(T)(ref T[] arr, size_t newcapacity)


1. Shared modifies the type, so the template does not match. Even 
casting does not seem to work however. Is there something about 
shared that makes it unable to be taken by reference?
2. Is there a workaround for me to be able to preallocate the 
array?


Kind regards


Arrays of functions, function signatures and template instantiation

2013-04-29 Thread JR
I'm piecing together a small IRC bot as my second pet project, 
and next up is splitting the socket-listening/event handling into 
a separate thread.


TL;DR: skip to the link at the bottom -- can't it be done neater?


Raw IRC commands are strings whose format differs depending on 
the *type* of the IRC event (for lack of a better word). These 
event types are arbitrary short strings like "NICK", "PRIVMSG", 
"NOTICE", "PING", "001", etc. I'd sleep better if it were an 
enum, but as it is I'm parsing the type from the raw string by 
regex, so obviously I'm getting another string out of it. 
(Granted, you could cast them to that enum in a huge switch, but 
I'm not sure you'd gain any academic efficiency points 
considering the extra time spent in that switch.)


After some more regex I have an Event struct with string members 
like .sender, .target, .type, .content and some others. 
Naturally, depending on what actually happened I may want to 
react to it. Most on-event reactions are functions to pass the 
Event to, like onPrivateMessage(Event evt) -- but sometimes I 
want to know the impending server response of a command I just 
sent.


As an example, when you connect to a server, the first things you 
send are user details (full name etc) and a nickname request. If 
what the server sends next is the welcome event "001", then all 
is well -- wait for the end-of-motd event "376" and then slowly 
start joining your channels and doing your stuff. But if it is 
the nickname-in-use event "433", then everything stops until you 
have requested an available nick.


So I had in mind an event handler and a message dispatcher. The 
event handler would be in its own thread listening to the socket 
stream, and once it reads a string it would parse it into an 
Event, then pass it along to the message dispatcher. The 
dispatcher would keep a record of which threads have registered 
interest in receiving what events, and would send messages 
accordingly. The solution that springs to mind is an associative 
matrix/array-of-array where one of the index keys is the event 
type string, and the other is the thread ID (Tid).


But I still want to keep onPrivateMessage(Event evt) and friends 
around, so in a stroke of hubris I thought it would be neat if I 
could find a generic solution that could work with both arrays of 
thread IDs *and* arrays of function pointers. I'm not sure where 
the 'event handler' struct would end and where the 'message 
dispatcher' would start though -- perhaps I'll just combine them, 
call it Overlord and be done with it. Or maybe 
ResponsibilityCreep.


Much shotgun programming later and I now have two templates; 
MatrixWalker and FuncRunner, subject to serious renaming. (They 
were called Herp and Derp a few hours back.)


Given a function pointer and a matrix of type Foo[Tid][string], 
MatrixWalker will foreach all and invoke the function on both 
keys (Tid, string) and the final element Foo. The function 
signature must match the types used, hence the FuncRunner 
template as an adapter. Tid needn't be Tid unless it's in the 
context of messaging, naturally, and in the context of messaging 
Foo is irrelevant and could be bool. (Keeping a single array like 
Tid[string] would only allow for one event registered per Tid, so 
Tid has to be a key unless you could somehow store multiple 
values per key. Even if possible [?], deregistering the right Tid 
from an event string key wouldn't be straightforward anymore.)


Error: function expected before (), not func of type void 
function(string, uint)*

Yay! Woe.


http://dpaste.dzfl.pl/9273fb92

Can't it be done neater than this? It *does* work now, but it's 
incredibly hacky and I'm not satisfied with it. The whole 
'passing a function pointer to a function that casts the 
signature and invokes it' deal makes me cringe. :>



Many thanks in advance, would love any and every piece of advice 
you could spare. With some luck there are some easy shortcuts and 
I'm just too green to see them.


Error in template instantiation from D-Cookbook example

2018-02-09 Thread ShadoLight via Digitalmars-d-learn

Hi,

Trying to improve my CT-fu, I looked at a DSL example (chapter 9) 
in Adam's D-Cookbook. Although I am sure Adam's original examples 
would have worked, there were some errors in the example code in 
the book.


The example also contains some code to allow you to test the 
functions at RT, which had an error i.e. I had to change this...


writeln(parse(code));   // to aid with debugging
writeln(convertToD(parse(code)));   // debugging aid
..to..
writeln(parse(code)[]); // to aid with debugging
writeln(convertToD(parse(code))[]); // debugging aid

..to match the actual function arguments. So that worked fine.

However I could not get the CT version to work with the current 
version of DMD i.e. this [1]...


[1] https://run.dlang.io/is/dyElXg

...fails with:
onlineapp.d-mixin-36(38): Error: template argument expected 
following !
onlineapp.d(48): Error: template instance onlineapp.runDslCode!"5 
5 + 3 - 2 * 1 + 3 /" error instantiating.


I find the error message a bit lacking as to the real cause - I 
really cannot see where the "template argument expected following 
!" error is. It all looks correct to me.


In addition the RT version is working correctly (after fixing the 
above bug), so that is not helping in identifying the error - 
particularly since it is failing in the only CT specific function 
not used/called at RT. So I am not sure how to debug this.


Can somebody please put me out of my misery here?

Thx!



Template instantiation fails on Linux, succeeds on Windows

2018-05-17 Thread Bastiaan Veelo via Digitalmars-d-learn

Hi!

The code in [1] compiles and runs flawlessly on Windows, but not 
on Linux (neither run.dlang nor Travis docker image). Any idea 
what can be done?


errors:
Error: undefined identifier __va_list_tag
onlineapp.d(282): Error: template instance 
`onlineapp.SetFactory!byte` error instantiating

Error: undefined identifier __va_list_tag
onlineapp.d(288): Error: template instance 
`onlineapp.SetFactory!(Count)` error instantiating

Error: undefined identifier __va_list_tag
onlineapp.d(290): Error: template instance 
`onlineapp.SetFactory!char` error instantiating


SetFactory is defined on row 233, and it seems that the problem 
relates to the vararg opIndex.


[1] https://run.dlang.io/gist/6dcbe4e82846cbeb3bf478e92a2b6e6f


Getting the template name of a template instantiation

2016-06-27 Thread Nordlöw via Digitalmars-d-learn

If I have a template parameter

E = S!int

where

struct S(T) { S x; }

how can I extract the template name part `S` from E`?

Something like:

static assert(is(templateName!(S!int) == S));

Is this already in Phobos somewhere?


Re: Template instantiation and string vs const char[]

2014-09-03 Thread JR via Digitalmars-d-learn
On Wednesday, 3 September 2014 at 05:18:42 UTC, Jason den Dulk 
wrote:

[...]

While not really answering your question, I believe the idiomatic 
way is to use enum here instead of string/char[].


Conjecture: strings are final but the symbol can be redirected to 
point to new arrays, such as results of concatenations. 
Concatenations create new and unique arrays upon each operation 
as each by definition cannot be altered. char[] can be *appended* 
to, technically retaining the same array and merely reallocating 
(potentially moving) to fit the extra content.


This sounds like something the compiler should be able to work 
around but apparently it doesn't.


Also, note that your check of (R.length) will only evaluate to 
false if the template is instantiated as somet!().


Re: Shared, ref, arrays, and reserve template instantiation

2018-09-12 Thread Neia Neutuladh via Digitalmars-d-learn
On Wednesday, 12 September 2018 at 23:41:16 UTC, James Blachly 
wrote:
When I add the "shared" attribute to an array, I am no longer 
able to call reserve because the template won't instantiate:


Error: template object.reserve cannot deduce function from 
argument types !()(shared(int[]), int), candidates are:

/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4091):
  object.reserve(T)(ref T[] arr, size_t newcapacity)

1. Shared modifies the type, so the template does not match. 
Even casting does not seem to work however. Is there something 
about shared that makes it unable to be taken by reference?
2. Is there a workaround for me to be able to preallocate the 
array?


Kind regards


I'm guessing you tried something like:

shared char[] x;
// Doesn't work; it casts the result of x.reserve
cast(char[])x.reserve(100);
// Doesn't work; (cast(char[])x) is not an lvalue, so it 
can't be ref

(cast(char[])x).reserve(100);

Arrays are passed and stored like pointers, and `reserve` 
modifies the array, which is why the thing needs to be ref.


Anyway, it works like this:

// Cast and store in a variable so it can be ref
auto b = cast(char[]) x;
// Okay, reallocates b (changes b.ptr), doesn't change x
b.reserve(100);
// Copy changes back to the shared variable
x = cast(shared) b;



Re: Shared, ref, arrays, and reserve template instantiation

2018-09-12 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, September 12, 2018 5:41:16 PM MDT James Blachly via 
Digitalmars-d-learn wrote:
> When I add the "shared" attribute to an array, I am no longer
> able to call reserve because the template won't instantiate:
>
> Error: template object.reserve cannot deduce function from
> argument types !()(shared(int[]), int), candidates are:
> /dlang/dmd/linux/bin64/../../src/druntime/import/object.d(4091):
>object.reserve(T)(ref T[] arr, size_t newcapacity)
>
> 1. Shared modifies the type, so the template does not match. Even
> casting does not seem to work however. Is there something about
> shared that makes it unable to be taken by reference?
> 2. Is there a workaround for me to be able to preallocate the
> array?

You can't do much of anything with shared while it's shared, which is pretty
much the whole point. The way that shared needs to be used in general is
essentially

synchronized(mutexForSharedObj)
{
auto local = cast(Type)sharedObj;
// do stuff with local...

// ensure that no thread-local references to local / sharedObj exist
// before releasing the mutex
}

// shared object is now essentially unusable again

Doing pretty much _any_ operation on a shared object while it's shared
(other than atomic operations from core.atomic) is wrong, because it's not
thread-safe. The compiler prevents most operations but not as many as it
should (e.g. copying is currently legal). That will likely be fixed in the
future, but exactly what's going to happen to shared in all of the fine
details hasn't been sorted out yet. The basics work, but not all of the
details are as they should be yet.

So, if you're doing anything like calling reserve or ~= on a shared array,
then you need to protect it with the mutex that you have for it and cast
away shared first. However, if you're just dealing with constructing the
array, then what you should do is create it as thread-local and then cast it
to shared after you're done setting it up and are ready to share it across
threads (after which, all further operations on it should be protected by a
mutex or use atomics, otherwise they're not thread-safe).

- Jonathan M Davis





Re: Shared, ref, arrays, and reserve template instantiation

2018-09-12 Thread James Blachly via Digitalmars-d-learn

Great -- Thank you both.

I previously found Unqual, but it looks like that needs template 
support so wasn't feasible, hence my question.


Neia is right that I tried to cast as in the second case ( but 
without UFCS -- reserve( cast(int[]), N); ).  As an aside, what 
is going on behind the scenes with the compiler when casting away 
a property? I did not think cast operations copied data, so was 
surprised that a cast value is not an lvalue.


Regarding Jonathan's comments, we had definitely protected the ~= 
operations with Mutex, but realized we were doing lots of array 
appends in a hot loop, and since we have an idea of cardinality 
ahead of time just wanted to preallocate.  Since it is all 
initialization before concurrent code enters the picture, we'll 
do what you've suggested and set it up as TL and then cast to 
shared.


James


Re: Shared, ref, arrays, and reserve template instantiation

2018-09-12 Thread Jonathan M Davis via Digitalmars-d-learn
On Wednesday, September 12, 2018 9:42:19 PM MDT James Blachly via 
Digitalmars-d-learn wrote:
> Neia is right that I tried to cast as in the second case ( but
> without UFCS -- reserve( cast(int[]), N); ).  As an aside, what
> is going on behind the scenes with the compiler when casting away
> a property? I did not think cast operations copied data, so was
> surprised that a cast value is not an lvalue.

Well, you basically get a temporary variable when you cast an object, and
those are rvalues. And while casting with regards to type qualifiers such as
const or shared, you're not actually changing the data, plenty of other
casts do - e.g. float and long don't even have the same size, but you can
cast from one to the other. So, even in principle, only some casts could
result in lvalues even if we wanted them to.

- Jonathan M Davis





function(pointer) as template argument, explicit template instantiation

2021-12-30 Thread kdevel via Digitalmars-d-learn

```dptr.d
class R {
}

void foo (R r)
{
}

alias fn = void function (R);

void lyr (fn F) (R r)
{
}

immutable fn foo_ptr = &foo; // line 14
pragma (msg, typeof (foo_ptr));

auto ptr = lyr!(foo_ptr);// line 17
```
dmd reports:

```
immutable(void function(R))
dptr.d(14): Error: expression `& foo` is not a valid template 
value argument

```

If I comment out line 17 the code compiles. I want to put the 
explicitly instantiated function template into an immutable AA. 
How can that be phrased such that dmd compiles it?


Unique IDs for each template instantiation at compile-time?

2013-12-18 Thread Weasel
I was wondering if it was possible to generate unique(in order) 
IDs for each template instantiation of a class at compile-time.


A short example of what I'm trying to do:

static int counter = 0;
class A(T)
{
enum id = counter++;
}
class B : A!B
{
}

Ofcourse, this doesn't compile because the "counter" variable 
can't be read at compile-time.


assertion failure with template instantiation of forward reference class

2012-11-28 Thread comco

When trying to compile this code:

import std.stdio;
class A;

class B(T) : T {
}

void main() {
writeln(typeid(B!A));
}

I get this error: Assertion failure: '!scope' on line 358 in file 
'toobj.c'.
Shouldn't it be more like: Error: class main.A unable to resolve 
forward reference in definition


Looks like a bug?


Re: Arrays of functions, function signatures and template instantiation

2013-04-29 Thread anonymous

On Monday, 29 April 2013 at 23:49:18 UTC, JR wrote:
[...]

http://dpaste.dzfl.pl/9273fb92

Can't it be done neater than this? It *does* work now, but it's 
incredibly hacky and I'm not satisfied with it. The whole 
'passing a function pointer to a function that casts the 
signature and invokes it' deal makes me cringe. :>


To get rid of the cast:

13c13
<   void applyFunc(F* func, E[I][T] matrix) {
---

  void applyFunc(F func, E[I][T] matrix) {

16c16
<   func(major, minor, &element);
---

  func(major, minor, element);

29,30c29,30
<   void run(T major, I minor, F* func) {
<   (cast(void function(T,I))*func)(major, minor);
---

  void run(T major, I minor, F func) {
  func(major, minor);

52c52
<   alias
MatrixWalker!(typeof(runner),typeof(funcyMatrix)).applyFunc apply;
---
  alias 
MatrixWalker!(typeof(&runner),typeof(funcyMatrix)).applyFunc 
apply;


Re: Arrays of functions, function signatures and template instantiation

2013-04-30 Thread JR

On Tuesday, 30 April 2013 at 02:38:27 UTC, anonymous wrote:

To get rid of the cast:

[...]

Instantiating the template with a function parameter causes a 
compilation error when actually calling the function;


--
  asdf.d:13: Error: variable asdf.MatrixWalker!(@system 
void(string major, uint minor, void function(string, uint) func), 
void function(string, uint)[uint][string]).applyFunc.func cannot 
be declared to be a function
  asdf.d:16: Error: function expected before (), not func of type 
_error_

--

I have a vague feeling I had it working like that at one point 
but I cannot recall with any degree of certainty.


  1   2   >