www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Aliasing specialized template stuct in his module leads troubles

reply "Ivan Agafonov" <armadil yandex.ru> writes:
I have my library module:
========================================================
module mylib.vector;

// alias Vector!(float, 4) Vector4f;

struct Vector(T, uint size)
{
	T[size] array = 0;
	...
}
========================================================

And I have client module:
========================================================
import mylib.vector;

alias Vector!(float, 4) Vector4f;
	
void main()
{
	auto x = Vector4f([1.0f, 2.0f, 3.0f, 4.0f]);
}
========================================================

If alias would be in vector module (commented there) I will have 
to compile
both modules (otherwise I'll get link errors for some vector 
functions), but I want to simply import vector module and 
immediately use predefined aliases for vector template struct. 
How can I do this?
Sep 04 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Ivan Agafonov:

 (otherwise I'll get link errors for some vector functions),<

What errors and in what cases? Bye, bearophile
Sep 04 2012
prev sibling next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On 9/5/2012 7:46 AM, Ivan Agafonov wrote:
 I have my library module:
 ========================================================
 module mylib.vector;

 // alias Vector!(float, 4) Vector4f;

 struct Vector(T, uint size)
 {
      T[size] array = 0;
      ...
 }
 ========================================================

 And I have client module:
 ========================================================
 import mylib.vector;

 alias Vector!(float, 4) Vector4f;

 void main()
 {
      auto x = Vector4f([1.0f, 2.0f, 3.0f, 4.0f]);
 }
 ========================================================

 If alias would be in vector module (commented there) I will have to compile
 both modules (otherwise I'll get link errors for some vector functions),
 but I want to simply import vector module and immediately use predefined
 aliases for vector template struct. How can I do this?

If I understand your issue correctly, it isn't a "problem". It's the way D is designed to work. Simply importing a module does not mean that you do not also need to compile and link it in your program. What importing does is make the symbols (declarations, definitions and so on) in the module available at compile time so that the compiler can know what is and isn't visible to the module it is currently compiling. But if there are any symbols in the imported module that need to be present at link time (such as variable declarations), then the imported module needs to be compiled and linked as well. In other words, it doesn't work like Java, where importing a class file causes the related class to be loaded a runtime. Take the following example: ============================= // foo.d module foo; struct Bar { int x; } // baz.d module baz; import foo; void main() { Bar bar; bar.x = 1; } ============================= You can compile this example like so: dmd baz.d And you wind up with a working program. The struct definition in foo.d is just a definition. The compiler uses it to know what is and isn't callable on Bar, how much memory an instance of it needs, and so on. So you can declare and instantiate instances of it in other modules without compiling and linking the foo module. Now let's change it up a bit: ============================ // foo.d module foo; struct Bar { int x; } // Declare an instance of Bar here in the foo module Bar foobar; // baz.d module baz; import foo; void main() { Bar bar; bar.x = 1; foobar.x = 2; } ============================ Now compile like so: dmd baz.d And this happens: ============================ OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html baz.obj(baz) Error 42: Symbol Undefined _D3foo6foobarS3foo3Bar --- errorlevel 1 ============================ The reason is because when the compile processes baz.d, it sees that it uses the variable foobar. That variable is not found in the baz module, but it is publicly visible in the foo module which baz imports. So the compiler says, ok, this is no problem. It goes about its job and creates baz.obj and passes it off to the linker. The linker looks through baz.obj, finds a reference to foobar, which, given the name mangling (_D3foo6foobarS3foo3Bar), should exist in an object file called foo (the linker knows nothing about D modules). So the linker wants to take foo.obj and link it together with bar.obj to create the final executable. Only, there is no foo.obj because you didn't compile it. dmd baz.d foo.d Now both object files can be created and linked together to make the final executable. A template alias actually instantiates a template. A template instantiation must be available to the linker. So if you instantiate in the vector module, you *must* compile and link it. Generally, you should either pass all the modules you import along to the compiler, or link with a library in which those modules have been compiled. This way, you don't have to worry about what is declared or instantiated where.
Sep 04 2012
parent Mike Parker <aldacron gmail.com> writes:
On 9/5/2012 10:50 AM, Mike Parker wrote:

 compiler says, ok, this is no problem. It goes about its job and creates
 baz.obj and passes it off to the linker. The linker looks through
 baz.obj, finds a reference to foobar, which, given the name mangling
 (_D3foo6foobarS3foo3Bar), should exist in an object file called foo (the
 linker knows nothing about D modules). So the linker wants to take
 foo.obj and link it together with bar.obj to create the final
 executable. Only, there is no foo.obj because you didn't compile it.

And, I should probably say, this isn't actually accurate. The linker knows nothing about D name mangling either. But the point is, if a symbol the linker needs isn't available in any of the object files you pass to it, it will complain.
Sep 04 2012
prev sibling next sibling parent "Ivan Agafonov" <armadil yandex.ru> writes:
On Wednesday, 5 September 2012 at 01:49:50 UTC, Mike Parker wrote:
 On 9/5/2012 7:46 AM, Ivan Agafonov wrote:
 I have my library module:
 ========================================================
 module mylib.vector;

 // alias Vector!(float, 4) Vector4f;

 struct Vector(T, uint size)
 {
     T[size] array = 0;
     ...
 }
 ========================================================

 And I have client module:
 ========================================================
 import mylib.vector;

 alias Vector!(float, 4) Vector4f;

 void main()
 {
     auto x = Vector4f([1.0f, 2.0f, 3.0f, 4.0f]);
 }
 ========================================================

 If alias would be in vector module (commented there) I will 
 have to compile
 both modules (otherwise I'll get link errors for some vector 
 functions),
 but I want to simply import vector module and immediately use 
 predefined
 aliases for vector template struct. How can I do this?

If I understand your issue correctly, it isn't a "problem". It's the way D is designed to work. Simply importing a module does not mean that you do not also need to compile and link it in your program. What importing does is make the symbols (declarations, definitions and so on) in the module available at compile time so that the compiler can know what is and isn't visible to the module it is currently compiling. But if there are any symbols in the imported module that need to be present at link time (such as variable declarations), then the imported module needs to be compiled and linked as well. In other words, it doesn't work like Java, where importing a class file causes the related class to be loaded a runtime. Take the following example: ============================= // foo.d module foo; struct Bar { int x; } // baz.d module baz; import foo; void main() { Bar bar; bar.x = 1; } ============================= You can compile this example like so: dmd baz.d And you wind up with a working program. The struct definition in foo.d is just a definition. The compiler uses it to know what is and isn't callable on Bar, how much memory an instance of it needs, and so on. So you can declare and instantiate instances of it in other modules without compiling and linking the foo module. Now let's change it up a bit: ============================ // foo.d module foo; struct Bar { int x; } // Declare an instance of Bar here in the foo module Bar foobar; // baz.d module baz; import foo; void main() { Bar bar; bar.x = 1; foobar.x = 2; } ============================ Now compile like so: dmd baz.d And this happens: ============================ OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html baz.obj(baz) Error 42: Symbol Undefined _D3foo6foobarS3foo3Bar --- errorlevel 1 ============================ The reason is because when the compile processes baz.d, it sees that it uses the variable foobar. That variable is not found in the baz module, but it is publicly visible in the foo module which baz imports. So the compiler says, ok, this is no problem. It goes about its job and creates baz.obj and passes it off to the linker. The linker looks through baz.obj, finds a reference to foobar, which, given the name mangling (_D3foo6foobarS3foo3Bar), should exist in an object file called foo (the linker knows nothing about D modules). So the linker wants to take foo.obj and link it together with bar.obj to create the final executable. Only, there is no foo.obj because you didn't compile it. dmd baz.d foo.d Now both object files can be created and linked together to make the final executable. A template alias actually instantiates a template. A template instantiation must be available to the linker. So if you instantiate in the vector module, you *must* compile and link it. Generally, you should either pass all the modules you import along to the compiler, or link with a library in which those modules have been compiled. This way, you don't have to worry about what is declared or instantiated where.

Thank you, I anderstand this now. But this should not be true in some cases:
 A template alias actually instantiates a template.

future purposes, it should not instantiate each of them, sinse in code i can use any number of them, or not use at all. Real instantiation must be in the module, in which I use this aliases. I believe that this is the case, but with one factor - When I use this alias in main module compiller instantiatiates it in the module, in which it defined. I can't see the reasons by which compiller do so. Because if i put this aliases in main module or specialise in place (auto someVector = Vector!(float, 4)(0.5, ...);) compiller will not do so. And I think there will take place only one instance for each specialisation in every module in which they are used. So in which .obj file realisation appears? How many questions... PS: Sorry for my english.
Sep 04 2012
prev sibling parent "Ivan Agafonov" <armadil yandex.ru> writes:
On Tuesday, 4 September 2012 at 23:51:49 UTC, bearophile wrote:
 Ivan Agafonov:

 (otherwise I'll get link errors for some vector functions),<

What errors and in what cases?

Error 42: Symbol Undefined _D4time4math6vector16__T6VectorTfVi4Z6Vector8toStringMFZAya hello.obj(hello) Error 42: Symbol Undefined _D4time4math6vector16__T6VectorTfVi4Z6Vector6__initZ hello.obj(hello) Error 42: Symbol Undefined _D4time4math6vector16__T6VectorTfVi4Z6Vector6__ctorMFfZS4time4math6vector16__T6VectorTfVi4Z6Vector hello.obj(hello) Error 42: Symbol Undefined _D4time4math6vector16__T6VectorTfVi4Z6Vector6__ctorMFG4fZS4time4math6vector16__T6VectorTfVi4Z6Vector
Sep 04 2012