c++ - DMC 8.38n Bug - Static & Template
- Adrian Boeing (54/54) Nov 18 2003 There appears to be a bug with DMC in its use of static variables.
- Walter (1/1) Nov 19 2003 Yes, this is the right place to report bugs. I'll check it out. -Walter
- Adrian Boeing (56/57) Dec 28 2003 Hi, I'm just wondering if you've gotten around to looking at this yet?
- dan (23/25) Dec 28 2003 Writing it clearly might be a start. Why call a function "PrintX()" when...
- Adrian Boeing (67/75) Jan 04 2004 Sure, added some clearer code with comments. This code is not the actual...
- Arjan Knepper (13/114) Jan 05 2004 Well quickly glancing over the code provided, I would say you're right,
- Adrian Boeing (6/18) Jan 07 2004 Hi Arjan,
There appears to be a bug with DMC in its use of static variables. This code compiles and works fine with VC6,GCC3.2,and IntelC 7.1: #include <stdio.h> #include <vector> #define VECTOR std::vector template <typename T> class A { public: void PrintX() { printf("x size:%d\n",vector().size()); } static std::vector<T>& vector() { static std::vector<T> instance; return instance; } }; template <typename T> class B { public: void SetA(T &t) { A<T>::vector().push_back(t); printf("B::SetA, x size:%d\n",A<T>::vector().size()); } }; class C : public B<int> { public: C() { printf("C\n"); int val=77; SetA(val); } }; C global_variable_c; int main() { C c; A<int> a; a.PrintX(); } The output produced by all other compilers is: C B::SetA, x size:1 C B::SetA, x size:2 x size:2 But for DMC the output is: C B::SetA, x size:1 C B::SetA, x size:1 x size:1 Thanks. If anyone can tell me a work-around that would also be usefull. PS:Im not sure where the bug reports are supposed to go. Here?
Nov 18 2003
Yes, this is the right place to report bugs. I'll check it out. -Walter
Nov 19 2003
In article <bpfj9g$2qna$1 digitaldaemon.com>, Walter says...Yes, this is the right place to report bugs. I'll check it out. -WalterHi, I'm just wondering if you've gotten around to looking at this yet? Can anyone suggest a work-around so that the program will run correctly? Is there some method to order the initialization of static variables? (something like #pragma init_seg for MSVC?) Thanks. Here is the example code again: #include <stdio.h> #include <vector> #define VECTOR std::vector template <typename T> class A { public: void PrintX() { printf("x size:%d\n",vector().size()); } static std::vector<T>& vector() { static std::vector<T> instance; return instance; } }; template <typename T> class B { public: void SetA(T &t) { A<T>::vector().push_back(t); printf("B::SetA, x size:%d\n",A<T>::vector().size()); } }; class C : public B<int> { public: C() { printf("C\n"); int val=77; SetA(val); } }; C global_variable_c; int main() { C c; A<int> a; a.PrintX(); } And the correct(ie: what I want) program output: C B::SetA, x size:1 C B::SetA, x size:2 x size:2 But for DMC the output is: C B::SetA, x size:1 C B::SetA, x size:1 x size:1 Thank You!
Dec 28 2003
Hi, I'm just wondering if you've gotten around to looking at this yet? Can anyone suggest a work-around so that the program will run correctly?Writing it clearly might be a start. Why call a function "PrintX()" when it is printing the size of an array? Wouldn't it make more sense to call it "PrintArraySize()"? One of the most basic principles of good coding is that of separating commands from queries. Queries return a value but are class const. Commands are non-const and return void. And you never write a function that causes side-effects that aren't obvious from the functon name. If you *need* to print from a constructor, such as to have a log of when it executes, it should print something like "class C's default ctor executing", not just "C". As it is, your code is so inscrutable I find it impossible to help you, as I get lost trying to understand it. And no, there is no way to determine the order of static initialization. And there will never be; otherwise we'd have to have a language within the language. What you can do is replace static variables with functions, so that if static int A is defined in terms of static int B, then static int A(){...} can simply call static int B(){...} during its initialization. If B is a constant primitive, like 77, just write it like static int B(){ return 77; } for consistency; and everything will work out; it's called lazy initialization. But it might be a problem when using such "constants" where a compile time constant is needed, such as in sizing an array. Templates might be better in such case, some basic metaprogramming. But in most cases, compile time constants are not needed if the design is done right: Use vector, instead of array, etc. HTH
Dec 28 2003
Hi, Thanks for the reply. (updated code at end)Writing it clearly might be a start. Why call a function "PrintX()" when it is printing the size of an array? Wouldn't it make more sense to call it "PrintArraySize()"?Sure, added some clearer code with comments. This code is not the actual code I am trying to use, it is just a simplified version which illustrates the problem. This is why the code appears to do "nothing"And no, there is no way to determine the order of static initialization. And there will never be; otherwise we'd have to have a language within the language.Shame. That could have solved this problem.What you can do is replace static variables with functions, so that if static int A is defined in terms of static int B, then static int A(){...} can simply call static int B(){...} during its initialization.This is what I have tried to do, which is why class A's returnvectorinstance simply returns an instance of a static vector. The desired output: class C's default ctor executing class B::AddToVector::Vector size:1 class C's default ctor executing class B::AddToVector::Vector size:2 Vector size:2 DMC's output: class C's default ctor executing class B::AddToVector::Vector size:1 class C's default ctor executing class B::AddToVector::Vector size:1 Vector size:1 Sorry for any confusion caused. Here is the code again: #include <stdio.h> #include <stdlib.h> #include <vector> template <typename T> class A { public: //this displays the number of items in the array static void PrintArraySize() { printf("Vector size:%d\n",returnvectorinstance().size()); } //this should ensure that the vector exists. static std::vector<T>& returnvectorinstance() { static std::vector<T> instance; return instance; } }; template <typename T> class B { public: //this adds an entry to the static vector, in class A void AddToVector(T &t) { A<T>::returnvectorinstance().push_back(t); printf("class B::AddToVector::"); A<T>::PrintArraySize(); } }; class C : public B<int> { public: //C's default ctor adds a value to A's static vector C() { printf("class C's default ctor executing\n"); int val=rand(); AddToVector(val); } }; C global_variable_c; //this variable should add an entry to A's static vector (ie: 1 entry) int main() { C c; //this variable should increment the number of entrys in A's static vector (ie: 2 entries) A<int> a; a.PrintArraySize(); //with VC,gcc,and icc a.PrintArraySize, will print "2". //however, with DMC it will print "1". }
Jan 04 2004
Well quickly glancing over the code provided, I would say you're right, it should return 2. Have you tried to make 'returnvectorinstance()' _not_ a class member? e.g: template < class T > static vector < T > &returnvectorinstance () { static vector<T> instance; return instance; } This should work even with 8.38 (I'm using the same contruct and never had troubles) Arjan Knepper Adrian Boeing wrote:Hi, Thanks for the reply. (updated code at end)Writing it clearly might be a start. Why call a function "PrintX()" when it is printing the size of an array? Wouldn't it make more sense to call it "PrintArraySize()"?Sure, added some clearer code with comments. This code is not the actual code I am trying to use, it is just a simplified version which illustrates the problem. This is why the code appears to do "nothing"And no, there is no way to determine the order of static initialization. And there will never be; otherwise we'd have to have a language within the language.Shame. That could have solved this problem.What you can do is replace static variables with functions, so that if static int A is defined in terms of static int B, then static int A(){...} can simply call static int B(){...} during its initialization.This is what I have tried to do, which is why class A's returnvectorinstance simply returns an instance of a static vector. The desired output: class C's default ctor executing class B::AddToVector::Vector size:1 class C's default ctor executing class B::AddToVector::Vector size:2 Vector size:2 DMC's output: class C's default ctor executing class B::AddToVector::Vector size:1 class C's default ctor executing class B::AddToVector::Vector size:1 Vector size:1 Sorry for any confusion caused. Here is the code again: #include <stdio.h> #include <stdlib.h> #include <vector> template <typename T> class A { public: //this displays the number of items in the array static void PrintArraySize() { printf("Vector size:%d\n",returnvectorinstance().size()); } //this should ensure that the vector exists. static std::vector<T>& returnvectorinstance() { static std::vector<T> instance; return instance; } }; template <typename T> class B { public: //this adds an entry to the static vector, in class A void AddToVector(T &t) { A<T>::returnvectorinstance().push_back(t); printf("class B::AddToVector::"); A<T>::PrintArraySize(); } }; class C : public B<int> { public: //C's default ctor adds a value to A's static vector C() { printf("class C's default ctor executing\n"); int val=rand(); AddToVector(val); } }; C global_variable_c; //this variable should add an entry to A's static vector (ie: 1 entry) int main() { C c; //this variable should increment the number of entrys in A's static vector (ie: 2 entries) A<int> a; a.PrintArraySize(); //with VC,gcc,and icc a.PrintArraySize, will print "2". //however, with DMC it will print "1". }
Jan 05 2004
Hi Arjan, Thank you, the example you provided works fine. Hopefully the bug will be fixed anyway. Cheers, -Adrian In article <btc4id$u3$1 digitaldaemon.com>, Arjan Knepper says...Well quickly glancing over the code provided, I would say you're right, it should return 2. Have you tried to make 'returnvectorinstance()' _not_ a class member? e.g: template < class T > static vector < T > &returnvectorinstance () { static vector<T> instance; return instance; } This should work even with 8.38 (I'm using the same contruct and never had troubles) Arjan Knepper
Jan 07 2004