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