Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. problem exporting static template data members, but not methods

problem exporting static template data members, but not methods

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestioncsharpc++visual-studio
8 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Marcello
    wrote on last edited by
    #1

    Hello, Visual Studio 2005 From the help on: Compiler Warning (level 2) C4356 If I modify that example like:#include <iostream> template <class T> class C { static int n; }; class D : C<int> {}; // int D::n = 0; // C4356 int C<int>::n = 0;
    if I take this code and put it in a DLL like this:// file mydll.h : # if defined(MYLIB_EXPORTS) # define MYLIB_API __declspec(dllexport) # else # define MYLIB_API __declspec(dllimport) # endif template <class T> class C { static int n; static void show() { std::cout << "C:show()" << std::endl; std::cout << n << std::endl; } }; class MYLIB_API D : C<int> {}; // file mydll.cpp : // initialization of static member int C<int>::n = 3; // file myapp.cpp : #include "mydll.h" int main() { int k1 = D::n; // (a) error LNK2001: unresolved external symbol int k2 = C<int>::n; // (b) error LNK2001: unresolved external symbol D::show(); // Okay }
    The error I get, if I uncomment (a) or (b), is always: 1>myapp.obj : error LNK2001: unresolved external symbol "public: static int C<int>::n" (?n@?$C@H@@2HA) This makes sense because I am not exporting C. So the question is: 1.1) Why then method show() gets exported ? 1.2) In other words: Why the method gets exported and the data member not ? 2) Is there any way to export directly the data ? ( of course I could workaround the problem and access the static data member through a static method ) 3) A last question, a little different, but maybe related: If I try to export some data from a DLL, like: // file mydll.h : static MYLIB_API int mydata; // error C2201: 'mydata' : must have external linkage in order to be exported/imported MYLIB_API static int mydata2; // error C2201: 'mydata' : must have external linkage in order to be exported/imported I think that with vc70, if I remember well, I was not gettting any error message while compiling the DLL, but the LNK2001 error when linking the application. In other words I am always forced to export data as static data member of a class, ( which is in some cases very unconvenient), like:// file mydll.h : class MYLIB_API MyDataClass { static int data; }; // file mydll.cpp : int MyDataClass::data = 5;
    Is there a way to do it without using a class ? Thank you very much for

    M B M 3 Replies Last reply
    0
    • M Marcello

      Hello, Visual Studio 2005 From the help on: Compiler Warning (level 2) C4356 If I modify that example like:#include <iostream> template <class T> class C { static int n; }; class D : C<int> {}; // int D::n = 0; // C4356 int C<int>::n = 0;
      if I take this code and put it in a DLL like this:// file mydll.h : # if defined(MYLIB_EXPORTS) # define MYLIB_API __declspec(dllexport) # else # define MYLIB_API __declspec(dllimport) # endif template <class T> class C { static int n; static void show() { std::cout << "C:show()" << std::endl; std::cout << n << std::endl; } }; class MYLIB_API D : C<int> {}; // file mydll.cpp : // initialization of static member int C<int>::n = 3; // file myapp.cpp : #include "mydll.h" int main() { int k1 = D::n; // (a) error LNK2001: unresolved external symbol int k2 = C<int>::n; // (b) error LNK2001: unresolved external symbol D::show(); // Okay }
      The error I get, if I uncomment (a) or (b), is always: 1>myapp.obj : error LNK2001: unresolved external symbol "public: static int C<int>::n" (?n@?$C@H@@2HA) This makes sense because I am not exporting C. So the question is: 1.1) Why then method show() gets exported ? 1.2) In other words: Why the method gets exported and the data member not ? 2) Is there any way to export directly the data ? ( of course I could workaround the problem and access the static data member through a static method ) 3) A last question, a little different, but maybe related: If I try to export some data from a DLL, like: // file mydll.h : static MYLIB_API int mydata; // error C2201: 'mydata' : must have external linkage in order to be exported/imported MYLIB_API static int mydata2; // error C2201: 'mydata' : must have external linkage in order to be exported/imported I think that with vc70, if I remember well, I was not gettting any error message while compiling the DLL, but the LNK2001 error when linking the application. In other words I am always forced to export data as static data member of a class, ( which is in some cases very unconvenient), like:// file mydll.h : class MYLIB_API MyDataClass { static int data; }; // file mydll.cpp : int MyDataClass::data = 5;
      Is there a way to do it without using a class ? Thank you very much for

      M Offline
      M Offline
      Maxwell Chen
      wrote on last edited by
      #2

      static tokens are only seen in the scope of that specific compilation unit.


      Maxwell Chen

      S 1 Reply Last reply
      0
      • M Maxwell Chen

        static tokens are only seen in the scope of that specific compilation unit.


        Maxwell Chen

        S Offline
        S Offline
        Stephen Hewitt
        wrote on last edited by
        #3

        This is not the case when the static keyword is used on a class member: in this case it means that the member is shared across all instances of the class and can be accessed without a this pointer. Just for interests sake, the use of static to make a global variable or function private to a compilation unit is deprecated in C++. The recommended way to achieve this effect is to use an anonymous namespace. i.e. namespace {      int g_Var; } Steve

        M 1 Reply Last reply
        0
        • S Stephen Hewitt

          This is not the case when the static keyword is used on a class member: in this case it means that the member is shared across all instances of the class and can be accessed without a this pointer. Just for interests sake, the use of static to make a global variable or function private to a compilation unit is deprecated in C++. The recommended way to achieve this effect is to use an anonymous namespace. i.e. namespace {      int g_Var; } Steve

          M Offline
          M Offline
          Maxwell Chen
          wrote on last edited by
          #4

          :-D I was talking about this line.

          static MYLIB_API int mydata; // error C2201: 'mydata' : must have external linkage in order to be exported/imported


          Maxwell Chen

          1 Reply Last reply
          0
          • M Marcello

            Hello, Visual Studio 2005 From the help on: Compiler Warning (level 2) C4356 If I modify that example like:#include <iostream> template <class T> class C { static int n; }; class D : C<int> {}; // int D::n = 0; // C4356 int C<int>::n = 0;
            if I take this code and put it in a DLL like this:// file mydll.h : # if defined(MYLIB_EXPORTS) # define MYLIB_API __declspec(dllexport) # else # define MYLIB_API __declspec(dllimport) # endif template <class T> class C { static int n; static void show() { std::cout << "C:show()" << std::endl; std::cout << n << std::endl; } }; class MYLIB_API D : C<int> {}; // file mydll.cpp : // initialization of static member int C<int>::n = 3; // file myapp.cpp : #include "mydll.h" int main() { int k1 = D::n; // (a) error LNK2001: unresolved external symbol int k2 = C<int>::n; // (b) error LNK2001: unresolved external symbol D::show(); // Okay }
            The error I get, if I uncomment (a) or (b), is always: 1>myapp.obj : error LNK2001: unresolved external symbol "public: static int C<int>::n" (?n@?$C@H@@2HA) This makes sense because I am not exporting C. So the question is: 1.1) Why then method show() gets exported ? 1.2) In other words: Why the method gets exported and the data member not ? 2) Is there any way to export directly the data ? ( of course I could workaround the problem and access the static data member through a static method ) 3) A last question, a little different, but maybe related: If I try to export some data from a DLL, like: // file mydll.h : static MYLIB_API int mydata; // error C2201: 'mydata' : must have external linkage in order to be exported/imported MYLIB_API static int mydata2; // error C2201: 'mydata' : must have external linkage in order to be exported/imported I think that with vc70, if I remember well, I was not gettting any error message while compiling the DLL, but the LNK2001 error when linking the application. In other words I am always forced to export data as static data member of a class, ( which is in some cases very unconvenient), like:// file mydll.h : class MYLIB_API MyDataClass { static int data; }; // file mydll.cpp : int MyDataClass::data = 5;
            Is there a way to do it without using a class ? Thank you very much for

            B Offline
            B Offline
            Branislav
            wrote on last edited by
            #5

            A data member of a class can be declared static; be it in the public or private part of the class definition. Such a data member is created and initialized only once, in contrast to non-static data members, which are created again and again, for each separate object of the class. A static data member is created once: when the program starts executing. Nonetheless, it is still part of the class. Static data members which are declared public are like `normal' global variables: they can be reached by all code of the program using their name, together with their class name and the scope resolution operator. This is illustrated in the following code fragment: #include template class C { public: static int n; }; The data member n is a private static variable. During the execution of the program, only one C::n exists, even though more than one object of the class C may exist. This data member could be inspected or altered by the constructor, destructor or by any other member function of the class C.

            1 Reply Last reply
            0
            • M Marcello

              Hello, Visual Studio 2005 From the help on: Compiler Warning (level 2) C4356 If I modify that example like:#include <iostream> template <class T> class C { static int n; }; class D : C<int> {}; // int D::n = 0; // C4356 int C<int>::n = 0;
              if I take this code and put it in a DLL like this:// file mydll.h : # if defined(MYLIB_EXPORTS) # define MYLIB_API __declspec(dllexport) # else # define MYLIB_API __declspec(dllimport) # endif template <class T> class C { static int n; static void show() { std::cout << "C:show()" << std::endl; std::cout << n << std::endl; } }; class MYLIB_API D : C<int> {}; // file mydll.cpp : // initialization of static member int C<int>::n = 3; // file myapp.cpp : #include "mydll.h" int main() { int k1 = D::n; // (a) error LNK2001: unresolved external symbol int k2 = C<int>::n; // (b) error LNK2001: unresolved external symbol D::show(); // Okay }
              The error I get, if I uncomment (a) or (b), is always: 1>myapp.obj : error LNK2001: unresolved external symbol "public: static int C<int>::n" (?n@?$C@H@@2HA) This makes sense because I am not exporting C. So the question is: 1.1) Why then method show() gets exported ? 1.2) In other words: Why the method gets exported and the data member not ? 2) Is there any way to export directly the data ? ( of course I could workaround the problem and access the static data member through a static method ) 3) A last question, a little different, but maybe related: If I try to export some data from a DLL, like: // file mydll.h : static MYLIB_API int mydata; // error C2201: 'mydata' : must have external linkage in order to be exported/imported MYLIB_API static int mydata2; // error C2201: 'mydata' : must have external linkage in order to be exported/imported I think that with vc70, if I remember well, I was not gettting any error message while compiling the DLL, but the LNK2001 error when linking the application. In other words I am always forced to export data as static data member of a class, ( which is in some cases very unconvenient), like:// file mydll.h : class MYLIB_API MyDataClass { static int data; }; // file mydll.cpp : int MyDataClass::data = 5;
              Is there a way to do it without using a class ? Thank you very much for

              M Offline
              M Offline
              Marcello
              wrote on last edited by
              #6

              Thank you for the all answers. But the question I made is not a beginner's question. It is about exporting a static variable and if there is any reason why it is made so difficult to export it. We know that it is possible to export a static member from a template class specialization, We know that it is not possible to use the __declspec(dllexport) keyword with a template. But in the example I gave I was able to get a static methods of a template exported even if the __declspec(dllexport) was not used. But this is not happening with a static data member. The reason I am trying to do this is that I need to export and use a class created by using the Curiously Recurring Template Pattern (CRTP). In my case the template base class needs to have a static member. About the third question, I am pretty sure that it is possible by using an export file (.def) and using a special keyword in it [ unfortunately I don't remember exactly how :( ]. Cheers, Marcello

              B 1 Reply Last reply
              0
              • M Marcello

                Thank you for the all answers. But the question I made is not a beginner's question. It is about exporting a static variable and if there is any reason why it is made so difficult to export it. We know that it is possible to export a static member from a template class specialization, We know that it is not possible to use the __declspec(dllexport) keyword with a template. But in the example I gave I was able to get a static methods of a template exported even if the __declspec(dllexport) was not used. But this is not happening with a static data member. The reason I am trying to do this is that I need to export and use a class created by using the Curiously Recurring Template Pattern (CRTP). In my case the template base class needs to have a static member. About the third question, I am pretty sure that it is possible by using an export file (.def) and using a special keyword in it [ unfortunately I don't remember exactly how :( ]. Cheers, Marcello

                B Offline
                B Offline
                Branislav
                wrote on last edited by
                #7

                "Windows requires all public symbols to be explicitly exported from a DLL via the __declspec(dllexport) syntax (and correspondingly dllimported when referenced in some other DLL). I guess it works pretty well on C libraries. But it doesn't work so well on C++ libraries, particularly with template classes--the template itself, of course, doesn't have a link-time presence, so it doesn't make sense to dllexport a template. What you really mean to export is the template instantatiation. But template instantiations are implicit, according to the language, so where do you put the dllexport syntax? Microsoft came up with a place to put the dllexport syntax, which is to explicitly put a line like this in the DLL that exports a particular template instance: Code: template class __declspec(dllexport) my_template_class; And also put a line like this in a DLL that imports that template instance: Code: extern template class __declspec(dllimport) my_template_class; These lines must be the first instantiation of the template instance, which means they must be seen by the compiler before any other reference to my_template_class. Of course, this is a Microsoft extension to C++ syntax; the language itself does not require this sort of declaration (and non-Microsoft compilers won't understand it). The problem with this declaration is that it explicitly expands and exports all methods and components of the template class, whether they are actually used or not; and it requires that nested template classes be explicitly exported before their containing classes are exported. That's not too bad, but it turns out that the standard STL implementation of list, map, set, multiset, multimap--basically everything other than vector--use nested template classes that are mutually recursive. That is, the nested class includes references to the containing class, and vice-versa. This makes it impossible to export the nested classes first, since expanding them requires expanding the containing class--which has not been exported yet, violating the rule that the export syntax must appear before the first instance is encountered. Similarly, you can't export the containing class first, which would expand the nested class before its export syntax. This means that none of the STL classes except for vector can be exported from a DLL. But do you really need to export a template instance from a DLL? Isn't each instance of a template technically a completely new copy of the class? If you don't even try to e

                M 1 Reply Last reply
                0
                • B Branislav

                  "Windows requires all public symbols to be explicitly exported from a DLL via the __declspec(dllexport) syntax (and correspondingly dllimported when referenced in some other DLL). I guess it works pretty well on C libraries. But it doesn't work so well on C++ libraries, particularly with template classes--the template itself, of course, doesn't have a link-time presence, so it doesn't make sense to dllexport a template. What you really mean to export is the template instantatiation. But template instantiations are implicit, according to the language, so where do you put the dllexport syntax? Microsoft came up with a place to put the dllexport syntax, which is to explicitly put a line like this in the DLL that exports a particular template instance: Code: template class __declspec(dllexport) my_template_class; And also put a line like this in a DLL that imports that template instance: Code: extern template class __declspec(dllimport) my_template_class; These lines must be the first instantiation of the template instance, which means they must be seen by the compiler before any other reference to my_template_class. Of course, this is a Microsoft extension to C++ syntax; the language itself does not require this sort of declaration (and non-Microsoft compilers won't understand it). The problem with this declaration is that it explicitly expands and exports all methods and components of the template class, whether they are actually used or not; and it requires that nested template classes be explicitly exported before their containing classes are exported. That's not too bad, but it turns out that the standard STL implementation of list, map, set, multiset, multimap--basically everything other than vector--use nested template classes that are mutually recursive. That is, the nested class includes references to the containing class, and vice-versa. This makes it impossible to export the nested classes first, since expanding them requires expanding the containing class--which has not been exported yet, violating the rule that the export syntax must appear before the first instance is encountered. Similarly, you can't export the containing class first, which would expand the nested class before its export syntax. This means that none of the STL classes except for vector can be exported from a DLL. But do you really need to export a template instance from a DLL? Isn't each instance of a template technically a completely new copy of the class? If you don't even try to e

                  M Offline
                  M Offline
                  Marcello
                  wrote on last edited by
                  #8

                  Thank you so much for your answer, and for saving me a lot of time and trouble. You really went to the core of problem I am having. Unfortunately I worked for months to recode my program in separate DLL's in order to keep things separated. I personally think that DLL are also a mean to keep things separated, so to unify all of them in a unique DLL is something I will do only if I have no other choice. In my case I think I would rather find a way to eliminate the static member, even if it is really not a good solution because of the way my class is supposed to be used. Only a question. Why in Unix you didn't meet this problem ? ( I know a bit about Linux, but not very much. ) Best Regards, Marcello

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups