0

i have the following code in a DLL, in a header file called TemplateT:

#pragma once

template<class T>
class __declspec(dllexport) TemplateT {
public:
    static int number;
    TemplateT(int num) {
        number = num;
    }
    int getNumber() {
        return number;
    }

};
template<class T>
int TemplateT<T>::number;

and on another header file called Exported.h

#pragma once
#include "TemplateT.h"


#define EXPORTED __declspec(dllexport)

extern EXPORTED TemplateT<int> exported;

and on Exported.cpp i have:

#include "Exporter.h"


TemplateT<int> exported(5);

As you can see, im initiating the static member "number" to the value of 5. but as i access the variable from another project like this:

#include <iostream>
#include "Exporter.h"

int main()
{
    int a = exported.getNumber();
    int b = 0;
}

i see the value of number as 0. Ill be happy if you could explain to me this behavior.

EDIT

both are used with visual studio 2019. the dll is compiled with vs19 and the other project with vs10

I found a question about the same situation, but the answers there did not fix it for me

two instances of static member

Ðаn
  • 10,934
  • 11
  • 59
  • 95
orah1998
  • 21
  • 3

2 Answers2

0

[SO]: DLL-Exporting static members of template base class provides an answer.
Your class (and exported variable) has 2 instances of the static member:

  1. In the .dll (Exporter.cpp) - initialized (explicitly) to 5
  2. In the .exe (main.cpp) - initialized (default) to 0 (this is the one you're actually seeing)

I replicated your code with minor changes - the most important one is the extra (regular .dll export) file

Export.h:

#pragma once

#if defined(_WIN32)
#  if defined(DLL0_STATIC)
#    define DLL0_EXPORT_API
#  else
#    if defined(DLL0_EXPORTS)
#      define DLL0_EXPORT_API __declspec(dllexport)
#    else
#      define DLL0_EXPORT_API __declspec(dllimport)
#    endif
#  endif
#else
#  define DLL0_EXPORT_API
#endif

Below are 2 screenshots took during debugging:

  1. Constructor

    img00

  2. Getter

    img01

Looking at the number member address (red boxed), it's different in the 2 pictures (note that the instance address (this) is the same), so there's the proof.

Now, looking at the bigger picture, this seems like an XY Problem.
I don't see any scenario (except for curiosity purposes only) where this design would fit, because the static member is set to the constructor argument, meaning that a new instance will overwrite whatever previous ones have set, so at a point in time, the member will contain the argument that was passed to the last instance constructor.

CristiFati
  • 38,250
  • 9
  • 50
  • 87
0

The #include instruction really means include. It effectively inserts the content of the included header file into the source file(.c/.cpp) (recursively).

So, when you (directly or indirectly) include your template.h in multiple source files, every source file will allocate it's own static number filed. If these source files are compiled into one target file, there will be a link error. But if they are compiled into difference DLL/EXEs, they will keep their own copy of that static filed.

This is similar to global varibles, in which you generally have to use extern keyword to tell the compiler this is just a declaration, not a definition.

Todd Wong
  • 234
  • 1
  • 4