Aliasing specialized template stuct in his module leads troubles

Ivan Agafonov armadil at yandex.ru
Tue Sep 4 20:30:59 PDT 2012


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.
This only aliases, and if I create many specializations for 
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.


More information about the Digitalmars-d-learn mailing list