Archives
D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
|
c++ - DMC 8.38n Bug - Static & Template
↑ ↓ ← → Adrian Boeing <Adrian_member pathlink.com> writes:
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?
↑ ↓ ← → "Walter" <walter digitalmars.com> writes:
Yes, this is the right place to report bugs. I'll check it out. -Walter
↑ ↓ ← → Adrian Boeing <Adrian_member pathlink.com> writes:
In article <bpfj9g$2qna$1 digitaldaemon.com>, Walter says...
Yes, this is the right place to report bugs. I'll check it out. -Walter
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?
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!
↑ ↓ ← → dan <dan_member pathlink.com> writes:
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
↑ ↓ ← → Adrian Boeing <Adrian_member pathlink.com> writes:
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".
}
↑ ↓ ← → Arjan Knepper <arjan ask.me> writes:
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".
}
↑ ↓ ← → Adrian Boeing <Adrian_member pathlink.com> writes:
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
|
|