http://groups.google.com/group/comp.lang.c++?hl=en
comp.lang.c++@googlegroups.com
Today's topics:
* trouble with STL list initialization inside nested structure - 2 messages, 2
authors
http://groups.google.com/group/comp.lang.c++/t/232c5d7f8d6e70f5?hl=en
* Throwing constructor for wrong type of objects - 5 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/4a947d40a7e46b31?hl=en
* A few questions about singletons... - 2 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/dd7f3af258a800cd?hl=en
* Const Static variables set at run time and a design question. - 1 messages,
1 author
http://groups.google.com/group/comp.lang.c++/t/b605293a5a67061f?hl=en
* Cross Compilation of C++ Code? - 8 messages, 5 authors
http://groups.google.com/group/comp.lang.c++/t/44a3671af0af55f6?hl=en
* Pass a pointer variable to a function accept reference - 1 messages, 1
author
http://groups.google.com/group/comp.lang.c++/t/330170d81fae3d1c?hl=en
* using local static variable inside a function - 3 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/7d53e8ea36d0502c?hl=en
==============================================================================
TOPIC: trouble with STL list initialization inside nested structure
http://groups.google.com/group/comp.lang.c++/t/232c5d7f8d6e70f5?hl=en
==============================================================================
== 1 of 2 ==
Date: Wed, Sep 30 2009 12:14 am
From: SG
M A wrote:
>
> typedef struct {
> list<struct row> bm;
> vector<struct row> vbm;
>
> } MyStruct;
This is a mixture of C and C++. You could write just as well
struct MyStruct {
list<row> bm;
vector<row> vbm;
};
> typedef struct pattern {
> int nodenum; // unique in the graph
> MyStruct ms;
> } TP;
same here
> int main(int args, char **argv)
> {
> TP *tp = (TP *) malloc (sizeof(TP));
> struct row r1 = {1, (char *)"xyz"};
> tp->ms.bm.push_back(r1);
> }
same here. Replace malloc with new and char* with std::string. Also, I
don't see a reason for using the free store. This should work too:
int main(int args, char **argv)
{
TP tp;
row r1 = {1, "xyz"}; // note: no "struct" prefix
tp.ms.bm.push_back(r1);
}
By the way: In C++ string literals are const. So, you better use
"const char*" instead of "char*". The latter one still compiles for
backwards compatibility to C. Since you're now allowed to modify the
characters of a string literal (not even in C) you'll only gain from
using const qualifiers here.
One last note: Try to improve encapsulation.
Cheers,
SG
== 2 of 2 ==
Date: Wed, Sep 30 2009 2:46 am
From: ytrembla@nyx.nyx.net (Yannick Tremblay)
In article <a64d6462-41f2-49ad-9925-5915d53ec564@t2g2000yqn.googlegroups.com>,
M A <medha.atre@gmail.com> wrote:
>Thanks for the explanation Joshua. I wasn't aware of intricate
>differences between "malloc" and "new"!
>I just made a quick fix as follows:
>------------------------------------
>
>typedef struct pattern {
> int nodenum; // unique in the graph
> MyStruct ms;
>} TP;
>
>int main(int args, char **argv)
>{
>
> TP *tp = new TP;
>
> struct row r1 = {1, (char *)"xyz"};
>
> tp->ms.bm.push_back(r1);
>
> list<struct row>::iterator itr = tp->ms.bm.begin();
>
> cout << (*itr).rowid << " " << (*itr).data << endl;
>}
>-------------------------------------
>And it is working now.
>Thanks a lot for your help. :)
Correction: you think it is working and it has not segfaulted on you
yet because in your test code you are using a static C string...
Let's look at it again:
> struct row {
> int rowid;
> char *data;
> bool operator<(const struct row &a) const {
> return (this->rowid < a.rowid);
> };
> };
OK, C++ containers use value semantic and copy data around. So what
will happen when you put this in a container is that the row will be
shallow copied element by element:
row r1 = { 1, (char *)"xyz" };
row r2 = r1;
now r1.data points to the "xyz" static string and r2.data point to the exact
same memory address. So if you modify the content of r1.data, you are
also modifying r2.
Things will become much worse if instead of using a static string
"xyz", you use some dynamic buffer inadvertently. Note that
dynamically allocating your char *data will not solve your problem,
only make it more complicated and create heap violation rather than
stack violation.
E.g.:
int main()
{
char *buffer = strdup("Oh dear!");
int i = 84;
TP tp;
row r1 = { i, buffer };
tp.ms.bm.push_back(r1);
// ...
free(buffer);
// ...
list<row>::iterator itr = tp->ms.bm.begin();
printf("%s\n", itr->data); // !!! Oh dear!
}
The simplest fix is:
struct row
{
int i;
std::string data;
bool operator<(const row &a) const {
return (this->rowid < a.rowid);
};
}
The alternative is to implement it all yourself with a constructor, a
copy constructor and an assignement operator that allocate a buffer
for data and copy the input as well as a destructor that release the
memory. But that's a waste of effort.
>typedef struct {
> list<struct row> bm;
> vector<struct row> vbm;
>} MyStruct;
C+, remove the unecessary typedef and struct:
struct MyStruct {
list<row> bm;
vector<row> vbm;
}
> typedef struct pattern {
> int nodenum; // unique in the graph
> MyStruct ms;
> } TP;
Again reomve unecessary typedef
>int main(int args, char **argv)
>{
> TP *tp = new TP;
Why dynamic allocation?
TP tp;
Works perfectly and should be the default. i.e. use new only when you must.
> struct row r1 = {1, (char *)"xyz"};
Unecessary struct
You are assigning r1.data to a static string. (unless you made the
change to use a std::string or created a contructor the strcpy the
input). This is likely to cause you problems as your program grow. I
don't think you are planning to only ever assing static C string to
rows, are you?
tp->ms.bm.push_back(r1);
}
Hope this helps. Unfortunately, moving from C to C++ means a lot of
unleanring to do.
Yannick
==============================================================================
TOPIC: Throwing constructor for wrong type of objects
http://groups.google.com/group/comp.lang.c++/t/4a947d40a7e46b31?hl=en
==============================================================================
== 1 of 5 ==
Date: Wed, Sep 30 2009 12:31 am
From: Vladimir Jovic
Balog Pal wrote:
> "Vladimir Jovic" <vladaspams@gmail.com>
>
>> As explained to Victor, the processing pipeline should be set dynamically.
>> Any attempt to create an invalid pipeline should be caught and the error
>> should be reported.
>
> If so, any attmpt to to solve the situation by overload-resolution is
> futile. You have to decide validity *inside* the function, and throw on an
> if()-like condition.
>
> You shall use some dynamic_cast, or a virtual function in the base interface
> that reports the attributes of your buffer.
>
>
That would be another approach : to add a common base class for all
BufferBase template classes, and use a dynamic_cast to expected buffer
type, and if the cast fails then to throw an exception. But I thought
there is a more elegant solution.
Too bad a trick with ellipses doesn't work :(
== 2 of 5 ==
Date: Wed, Sep 30 2009 12:49 am
From: Vladimir Jovic
Victor Bazarov wrote:
> Vladimir Jovic wrote:
>> [..]
>> Buffers (except for the source and destination) can be created in a
>> vector, list, or queue (different container objects for different base
>> buffer classes).
>
> Where do those live and what is the relationship between buffers of
> different types (instance of different templates) and the queue (one
> object) which is going to "connect buffers"?
>
Buffers are created on the heap, and are completely independent. The
requirements are that the first has to be the source buffer type, which
somehow gets input data (doesn't matter how), and the last has to be the
destination buffer type, where the resulting data is stored.
Data is of fixed size, which is known in front.
>> All filter objects will be stored in one container, and the data will
>> be processed in one run.
>
> OK, let's proceed with a simplified model. Let's have a queue of two
> filters, and make it create all the "buffers" for those and process the
> input to get to the output.
>
> struct Filter
> {
> virtual void setFrom(???);
> virtual void setTo(???);
>
> virtual void process(??, ??);
> };
>
It is actually simpler :
struct Filter
{
Filter( const BufferType1 &b1, BufferType2 &b2 );
virtual void Process();
};
or as you wrote it:
struct Filter
{
void SetFrom( const BufferType1 &b1 );
void SetTo( BufferType1 &b1 );
virtual void Process();
};
Only one combination of BufferType1/BufferType2 are valid for any Filter
type.
The Process() method reads data from the input buffer, process it, and
store the result in the output buffer.
> // now, is this queue generic or does it know how many filters
> // it has and what is the sequence of types it processes?
The queue is generic, and can be changed during the program execution.
It can contain any number of filters.
If it was static, I would not have this problem.
> struct FilterQueue
> {
> typedef std::list<Filter*> list;
> typedef list::iterator iterator;
>
> list filters;
>
> void append(Filter* pf) { filters.push_back(pf); }
>
> void createBuffers(???) {
> // the filters are added in 'append', here we need to add
> // all the buffers between the filters
>
> for (iterator it = filters.begin(); it != filters.end; ++it)
> {
> // it would seem that the buffers have to be *ALSO*
> // storable in some kind of container, no? Otherwise
> // how do you move from 'createBuffers' to 'process'?
> }
> }
>
> void process(???) {
> for (iterator it = filters.begin(); it != filters.end; ++it)
> it->process(??,??);
> }
> };
>
> I can only see more questions that haven't yet been answered. Do you
> have any answers?
There are actually two classes:
class BufferQueue
{
typedef std::list<Filter*> list;
typedef list::iterator iterator;
void CreateBuffers( ConfigType & )
{
list.push( sourceBuffer);
// create all intermediate buffers
list.push( destBuffer);
}
list buffers;
};
struct FilterQueue
{
typedef std::list<Filter*> list;
typedef list::iterator iterator;
list filters;
void CreateFilters( ConfigType &, BufferQueue & )
{
// read configuration
// create filters (types are defined in the configuration)
// connect buffers to each filter
}
void process() {
for (iterator it = filters.begin(); it != filters.end; ++it)
it->process();
}
};
== 3 of 5 ==
Date: Wed, Sep 30 2009 4:45 am
From: Victor Bazarov
Vladimir Jovic wrote:
> Victor Bazarov wrote:
>> Vladimir Jovic wrote:
>>> [..]
>>> Buffers (except for the source and destination) can be created in a
>>> vector, list, or queue (different container objects for different
>>> base buffer classes).
>>
>> Where do those live and what is the relationship between buffers of
>> different types (instance of different templates) and the queue (one
>> object) which is going to "connect buffers"?
>>
>
> Buffers are created on the heap, and are completely independent.
They can't be independent if they are put in a queue.
> The
> requirements are that the first has to be the source buffer type, which
> somehow gets input data (doesn't matter how), and the last has to be the
> destination buffer type, where the resulting data is stored.
>
> Data is of fixed size, which is known in front.
>
>>> All filter objects will be stored in one container, and the data will
>>> be processed in one run.
>>
>> OK, let's proceed with a simplified model. Let's have a queue of two
>> filters, and make it create all the "buffers" for those and process
>> the input to get to the output.
>>
>> struct Filter
>> {
>> virtual void setFrom(???);
>> virtual void setTo(???);
>>
>> virtual void process(??, ??);
>> };
>>
>
> It is actually simpler :
> struct Filter
> {
> Filter( const BufferType1 &b1, BufferType2 &b2 );
>
> virtual void Process();
> };
>
> or as you wrote it:
> struct Filter
> {
> void SetFrom( const BufferType1 &b1 );
> void SetTo( BufferType1 &b1 );
>
> virtual void Process();
> };
>
> Only one combination of BufferType1/BufferType2 are valid for any Filter
> type.
>
> The Process() method reads data from the input buffer, process it, and
> store the result in the output buffer.
>
>> // now, is this queue generic or does it know how many filters
>> // it has and what is the sequence of types it processes?
>
> The queue is generic, and can be changed during the program execution.
> It can contain any number of filters.
>
> If it was static, I would not have this problem.
>
>> struct FilterQueue
>> {
>> typedef std::list<Filter*> list;
>> typedef list::iterator iterator;
>>
>> list filters;
>>
>> void append(Filter* pf) { filters.push_back(pf); }
>>
>> void createBuffers(???) {
>> // the filters are added in 'append', here we need to add
>> // all the buffers between the filters
>>
>> for (iterator it = filters.begin(); it != filters.end; ++it)
>> {
>> // it would seem that the buffers have to be *ALSO*
>> // storable in some kind of container, no? Otherwise
>> // how do you move from 'createBuffers' to 'process'?
>> }
>> }
>>
>> void process(???) {
>> for (iterator it = filters.begin(); it != filters.end; ++it)
>> it->process(??,??);
>> }
>> };
>>
>> I can only see more questions that haven't yet been answered. Do you
>> have any answers?
>
> There are actually two classes:
>
> class BufferQueue
> {
> typedef std::list<Filter*> list;
^^^^^^
Really?
> typedef list::iterator iterator;
>
> void CreateBuffers( ConfigType & )
> {
> list.push( sourceBuffer);
What is 'sourceBuffer'? What type does it have? Is it convertible to
'Filter*'?
>
> // create all intermediate buffers
>
> list.push( destBuffer);
> }
>
> list buffers;
> };
>
> struct FilterQueue
> {
> typedef std::list<Filter*> list;
> typedef list::iterator iterator;
>
> list filters;
>
> void CreateFilters( ConfigType &, BufferQueue & )
> {
> // read configuration
> // create filters (types are defined in the configuration)
> // connect buffers to each filter
> }
>
>
> void process() {
> for (iterator it = filters.begin(); it != filters.end; ++it)
> it->process();
> }
> };
Seems like you got a few things to figure out, still.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
== 4 of 5 ==
Date: Wed, Sep 30 2009 4:59 am
From: Vladimir Jovic
Victor Bazarov wrote:
> Vladimir Jovic wrote:
>> Victor Bazarov wrote:
>>> Vladimir Jovic wrote:
>>>> [..]
>>>> Buffers (except for the source and destination) can be created in a
>>>> vector, list, or queue (different container objects for different
>>>> base buffer classes).
>>>
>>> Where do those live and what is the relationship between buffers of
>>> different types (instance of different templates) and the queue (one
>>> object) which is going to "connect buffers"?
>>>
>>
>> Buffers are created on the heap, and are completely independent.
>
> They can't be independent if they are put in a queue.
Not sure I understand. Why they wouldn't be independent?
>
> > The
>> requirements are that the first has to be the source buffer type,
>> which somehow gets input data (doesn't matter how), and the last has
>> to be the destination buffer type, where the resulting data is stored.
>>
>> Data is of fixed size, which is known in front.
>>
>>>> All filter objects will be stored in one container, and the data
>>>> will be processed in one run.
>>>
>>> OK, let's proceed with a simplified model. Let's have a queue of two
>>> filters, and make it create all the "buffers" for those and process
>>> the input to get to the output.
>>>
>>> struct Filter
>>> {
>>> virtual void setFrom(???);
>>> virtual void setTo(???);
>>>
>>> virtual void process(??, ??);
>>> };
>>>
>>
>> It is actually simpler :
>> struct Filter
>> {
>> Filter( const BufferType1 &b1, BufferType2 &b2 );
>>
>> virtual void Process();
>> };
>>
>> or as you wrote it:
>> struct Filter
>> {
>> void SetFrom( const BufferType1 &b1 );
>> void SetTo( BufferType1 &b1 );
>>
>> virtual void Process();
>> };
>>
>> Only one combination of BufferType1/BufferType2 are valid for any
>> Filter type.
>>
>> The Process() method reads data from the input buffer, process it, and
>> store the result in the output buffer.
>>
>>> // now, is this queue generic or does it know how many filters
>>> // it has and what is the sequence of types it processes?
>>
>> The queue is generic, and can be changed during the program execution.
>> It can contain any number of filters.
>>
>> If it was static, I would not have this problem.
>>
>>> struct FilterQueue
>>> {
>>> typedef std::list<Filter*> list;
>>> typedef list::iterator iterator;
>>>
>>> list filters;
>>>
>>> void append(Filter* pf) { filters.push_back(pf); }
>>>
>>> void createBuffers(???) {
>>> // the filters are added in 'append', here we need to add
>>> // all the buffers between the filters
>>>
>>> for (iterator it = filters.begin(); it != filters.end; ++it)
>>> {
>>> // it would seem that the buffers have to be *ALSO*
>>> // storable in some kind of container, no? Otherwise
>>> // how do you move from 'createBuffers' to 'process'?
>>> }
>>> }
>>>
>>> void process(???) {
>>> for (iterator it = filters.begin(); it != filters.end; ++it)
>>> it->process(??,??);
>>> }
>>> };
>>>
>>> I can only see more questions that haven't yet been answered. Do you
>>> have any answers?
>>
>> There are actually two classes:
>>
>> class BufferQueue
>> {
>> typedef std::list<Filter*> list;
> ^^^^^^
> Really?
>
Typo. Should have been Buffer*
>> typedef list::iterator iterator;
>>
>> void CreateBuffers( ConfigType & )
>> {
>> list.push( sourceBuffer);
>
> What is 'sourceBuffer'? What type does it have? Is it convertible to
> 'Filter*'?
>
It is not. The source and destination buffers are declared like this:
class SourceBuffer : public BufferBase< unsigned short >;
class DestinationBuffer : public BufferBase< unsigned char >;
>>
>> // create all intermediate buffers
>>
>> list.push( destBuffer);
>> }
>>
>> list buffers;
>> };
>>
Actually, since I got 3 base types (BufferBase is a template), there
should be 3 queues for each buffer type.
The idea is to have dump Buffer classes, which holds array as
intermediate data points, and to use Filter classes to transfer and
transform data from one point to another (from the source to the
destination/sink)
>> struct FilterQueue
>> {
>> typedef std::list<Filter*> list;
>> typedef list::iterator iterator;
>>
>> list filters;
>>
>> void CreateFilters( ConfigType &, BufferQueue & )
>> {
>> // read configuration
>> // create filters (types are defined in the configuration)
>> // connect buffers to each filter
>> }
>>
>>
>> void process() {
>> for (iterator it = filters.begin(); it != filters.end; ++it)
>> it->process();
>> }
>> };
>
> Seems like you got a few things to figure out, still.
Looked simple and straight-forward on the paper :/
== 5 of 5 ==
Date: Wed, Sep 30 2009 5:25 am
From: Victor Bazarov
Vladimir Jovic wrote:
> Victor Bazarov wrote:
>> Vladimir Jovic wrote:
>>> Victor Bazarov wrote:
>>>> Vladimir Jovic wrote:
>>>>> [..]
>>>>> Buffers (except for the source and destination) can be created in a
>>>>> vector, list, or queue (different container objects for different
>>>>> base buffer classes).
>>>>
>>>> Where do those live and what is the relationship between buffers of
>>>> different types (instance of different templates) and the queue (one
>>>> object) which is going to "connect buffers"?
>>>>
>>>
>>> Buffers are created on the heap, and are completely independent.
>>
>> They can't be independent if they are put in a queue.
>
> Not sure I understand. Why they wouldn't be independent?
>
>>
>> > The
>>> requirements are that the first has to be the source buffer type,
>>> which somehow gets input data (doesn't matter how), and the last has
>>> to be the destination buffer type, where the resulting data is stored.
>>>
>>> Data is of fixed size, which is known in front.
>>>
>>>>> All filter objects will be stored in one container, and the data
>>>>> will be processed in one run.
>>>>
>>>> OK, let's proceed with a simplified model. Let's have a queue of
>>>> two filters, and make it create all the "buffers" for those and
>>>> process the input to get to the output.
>>>>
>>>> struct Filter
>>>> {
>>>> virtual void setFrom(???);
>>>> virtual void setTo(???);
>>>>
>>>> virtual void process(??, ??);
>>>> };
>>>>
>>>
>>> It is actually simpler :
>>> struct Filter
>>> {
>>> Filter( const BufferType1 &b1, BufferType2 &b2 );
>>>
>>> virtual void Process();
>>> };
>>>
>>> or as you wrote it:
>>> struct Filter
>>> {
>>> void SetFrom( const BufferType1 &b1 );
>>> void SetTo( BufferType1 &b1 );
>>>
>>> virtual void Process();
>>> };
>>>
>>> Only one combination of BufferType1/BufferType2 are valid for any
>>> Filter type.
>>>
>>> The Process() method reads data from the input buffer, process it,
>>> and store the result in the output buffer.
>>>
>>>> // now, is this queue generic or does it know how many filters
>>>> // it has and what is the sequence of types it processes?
>>>
>>> The queue is generic, and can be changed during the program
>>> execution. It can contain any number of filters.
>>>
>>> If it was static, I would not have this problem.
>>>
>>>> struct FilterQueue
>>>> {
>>>> typedef std::list<Filter*> list;
>>>> typedef list::iterator iterator;
>>>>
>>>> list filters;
>>>>
>>>> void append(Filter* pf) { filters.push_back(pf); }
>>>>
>>>> void createBuffers(???) {
>>>> // the filters are added in 'append', here we need to add
>>>> // all the buffers between the filters
>>>>
>>>> for (iterator it = filters.begin(); it != filters.end; ++it)
>>>> {
>>>> // it would seem that the buffers have to be *ALSO*
>>>> // storable in some kind of container, no? Otherwise
>>>> // how do you move from 'createBuffers' to 'process'?
>>>> }
>>>> }
>>>>
>>>> void process(???) {
>>>> for (iterator it = filters.begin(); it != filters.end; ++it)
>>>> it->process(??,??);
>>>> }
>>>> };
>>>>
>>>> I can only see more questions that haven't yet been answered. Do
>>>> you have any answers?
>>>
>>> There are actually two classes:
>>>
>>> class BufferQueue
>>> {
>>> typedef std::list<Filter*> list;
>> ^^^^^^
>> Really?
>>
>
> Typo. Should have been Buffer*
So, what's a Buffer? Below you say it's a template. It can't be a
template if you are going to put it in a common BufferQueue. Or is it
not a common BufferQueue, but itself a template? Then you can't pass a
reference to it to a single function in FilterQueue either...
>
>>> typedef list::iterator iterator;
>>>
>>> void CreateBuffers( ConfigType & )
>>> {
>>> list.push( sourceBuffer);
>>
>> What is 'sourceBuffer'? What type does it have? Is it convertible to
>> 'Filter*'?
>>
>
> It is not. The source and destination buffers are declared like this:
> class SourceBuffer : public BufferBase< unsigned short >;
> class DestinationBuffer : public BufferBase< unsigned char >;
>
>
>>>
>>> // create all intermediate buffers
>>>
>>> list.push( destBuffer);
>>> }
>>>
>>> list buffers;
>>> };
>>>
>
> Actually, since I got 3 base types (BufferBase is a template), there
> should be 3 queues for each buffer type.
I am not sure I understand. 3 base types : BufferBase<unsigned char>,
BufferBase<unsigned short>, BufferBase<unsigned long>? Or something
else? So, do you have 3 queues which are also instantiations of some
class template? Consider spelling it out, don't expect me to pull it
out of you with pliers.
> The idea is to have dump Buffer classes, which holds array as
> intermediate data points, and to use Filter classes to transfer and
> transform data from one point to another (from the source to the
> destination/sink)
>
>>> struct FilterQueue
>>> {
>>> typedef std::list<Filter*> list;
>>> typedef list::iterator iterator;
>>>
>>> list filters;
>>>
>>> void CreateFilters( ConfigType &, BufferQueue & )
>>> {
>>> // read configuration
>>> // create filters (types are defined in the configuration)
>>> // connect buffers to each filter
>>> }
>>>
>>>
>>> void process() {
>>> for (iterator it = filters.begin(); it != filters.end; ++it)
>>> it->process();
>>> }
>>> };
>>
>> Seems like you got a few things to figure out, still.
>
> Looked simple and straight-forward on the paper :/
Start writing code. And start from the *use* of your classes, so you
can figure out the interfaces. Then try declaring the interfaces.
Forget about linking, try making it compile. Then add implementations
to some of your interfaces.
It's an iterative process. It looks very clean and straightforward in
one's head, sometimes on paper, but as soon as you try coding it, the
cleanliness and straightforwardness is usually gone (at least
temporarily until you figure it all out).
I recommend trying to get as much done as you can and repost when you
have more questions. Post real compilable (or almost compilable) code
at that time.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
==============================================================================
TOPIC: A few questions about singletons...
http://groups.google.com/group/comp.lang.c++/t/dd7f3af258a800cd?hl=en
==============================================================================
== 1 of 2 ==
Date: Wed, Sep 30 2009 12:54 am
From: Michael Doubez
On 30 sep, 01:48, "Chris M. Thomasson" <n...@spam.invalid> wrote:
> "Michael Doubez" <michael.dou...@free.fr> wrote in message
>
> news:5b98df17-4599-49bc-ba58-a5a31cc1d800@k17g2000yqb.googlegroups.com...
> On 25 sep, 20:45, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> [...]
>
> > > Alternatively, use the more complex designs of Chris M.
> > > Thomasson, which just guarantee single correct construction with
> > > minimal overhead. There are several, depending on platform, and
> > > exactly what guarantees you want.
> > I have seen the code mentioned and it supposes that initialisation of
> > the mutex is atomic.
> > If I replace in the header:
> > typedef HANDLE pthread_mutex_t;
> > #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
> > You see the problem with:
> > static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
> > In fact, it is possible that two mutex will be created and the mutex
> > is then useless.
> > In practice, IIRC it does work with the usual libpthread.
>
> Yes. The code I posted assumes that it will always be run under a POSIX
> compliant platform. However, since you bring up Windows, well, there is a
> hack one can use to dynamically and safely create a mutex in an atomic
> fashion:
>[snip]
> : m_mutex(CreateMutex(NULL, TRUE, prv_get_name().c_str()))
> [snip]
Yes, that solves the issue. It looks to me like creating a system wide
semaphore; well, not a worry really since the number of singleton
should be low.
--
Michael
== 2 of 2 ==
Date: Wed, Sep 30 2009 12:57 am
From: Michael Doubez
On 30 sep, 01:48, "Chris M. Thomasson" <n...@spam.invalid> wrote:
[snip]
> if (! m_mutex)
> {
> assert(m_mutex);
> std::unexpected();
> }
[snip]
I wondered about this usage of assert() + unexpected(): what is the
rational of using both ?
To tell the truth, I never use std::unexpected(). How and when do you
use it ?
--
Michael
==============================================================================
TOPIC: Const Static variables set at run time and a design question.
http://groups.google.com/group/comp.lang.c++/t/b605293a5a67061f?hl=en
==============================================================================
== 1 of 1 ==
Date: Wed, Sep 30 2009 12:57 am
From: James Kanze
On Sep 29, 12:55 pm, Jim <j...@astro.livjm.ac.uk> wrote:
> I've a set of data which has two spectra associated with each
> position. For each spectra you convert from an array position
> to a real value using an array offset, a delta and a
> velocity offset. These are common to all spectra of the same
> type and don't change through the program's run. Unfortunately
> I don't know them until I load the file, unless I hard code
> them and I don't want to do that. Only solution I can think
> of is to have a user-defined object called conversion which
> has const members set in the constructor and const accessor
> methods and have a static object in each type of the specific
> spectra classes which inherit from the spectra base class.
> Does this seem correct?
If the data can be made available before entering main, there's
no problem; something like:
int configuration = getIntFromEnvironment( "CONFIGVARNAME" ) ;
works fine. If you have to read the value from a file (whose
name is passed in argv, for example), then it's more difficult.
Perhaps something along the lines of:
ConfigurationData const* configData ;
would do the trick, with configData being set each time after
reading the values.
--
James Kanze
==============================================================================
TOPIC: Cross Compilation of C++ Code?
http://groups.google.com/group/comp.lang.c++/t/44a3671af0af55f6?hl=en
==============================================================================
== 1 of 8 ==
Date: Wed, Sep 30 2009 3:39 am
From: "fdm"
In a function I have:
namespace Validation
{
template<typename T, typename M, typename I, typename R, typename P>
void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
imageM, R & region, double & value) {
typedef T TransformType;
typedef M MetricType;
typedef I InterpolatorType;
TransformType::Pointer transform = TransformType::New();
MetricType::Pointer metric = MetricType::New();
InterpolatorType::Pointer interpolator = InterpolatorType::New();
On windows vista 64 in Visual Studio this compiles fine. But in Ubuntu 9.04
I get the error:
compute_metric.h:22: error: expected `;' before 'transform'
compute_metric.h:23: error: expected `;' before 'metric'
compute_metric.h:24: error: expected `;' before 'interpolator'
corresponding to the last three lines in the above code. I have made sure
that inlcudes are setup correctly, any ideas?
I have previously experienced that various statements are allowed in VS that
is not allowed on Linux.
== 2 of 8 ==
Date: Wed, Sep 30 2009 4:08 am
From: Michael Doubez
On 30 sep, 12:39, "fdm" <f...@gk.com> wrote:
> In a function I have:
>
> namespace Validation
> {
> template<typename T, typename M, typename I, typename R, typename P>
> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
> imageM, R & region, double & value) {
> typedef T TransformType;
> typedef M MetricType;
> typedef I InterpolatorType;
>
> TransformType::Pointer transform = TransformType::New();
> MetricType::Pointer metric = MetricType::New();
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
Those are type dependant name, shouldn't they require a 'typename'
before:
typename TransformType::Pointer transform = TransformType::New
();
typename MetricType::Pointer metric = MetricType::New();
typename InterpolatorType::Pointer interpolator = InterpolatorType::New
();
--
Michael
== 3 of 8 ==
Date: Wed, Sep 30 2009 4:09 am
From: Sam
fdm writes:
> In a function I have:
>
>
> namespace Validation
> {
> template<typename T, typename M, typename I, typename R, typename P>
> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
> imageM, R & region, double & value) {
> typedef T TransformType;
> typedef M MetricType;
> typedef I InterpolatorType;
>
> TransformType::Pointer transform = TransformType::New();
> MetricType::Pointer metric = MetricType::New();
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>
>
>
> On windows vista 64 in Visual Studio this compiles fine. But in Ubuntu 9.04
> I get the error:
>
> compute_metric.h:22: error: expected `;' before 'transform'
> compute_metric.h:23: error: expected `;' before 'metric'
> compute_metric.h:24: error: expected `;' before 'interpolator'
>
> corresponding to the last three lines in the above code. I have made sure
> that inlcudes are setup correctly, any ideas?
In a template definition context, it cannot be determined -- for example --
whether "TransformType::Pointer" refers to a member of the TransformType
class called "Pointer" which is an ordinary class member, or if this is a
type that's defined by the class.
You'll need to be more explicit:
class TransformType::Pointer transform = TransformType::New();
class MetricType::Pointer metric = MetricType::New();
class InterpolatorType::Pointer interpolator = InterpolatorType::New();
> I have previously experienced that various statements are allowed in VS that
> is not allowed on Linux.
gcc is much more strict on the language syntax than other compilers.
== 4 of 8 ==
Date: Wed, Sep 30 2009 4:09 am
From: "fdm"
"Michael Doubez" <michael.doubez@free.fr> wrote in message
news:d25e98ad-2ab6-41aa-a057-0a7cbedc5693@k19g2000yqc.googlegroups.com...
On 30 sep, 12:39, "fdm" <f...@gk.com> wrote:
> In a function I have:
>
> namespace Validation
> {
> template<typename T, typename M, typename I, typename R, typename P>
> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
> imageM, R & region, double & value) {
> typedef T TransformType;
> typedef M MetricType;
> typedef I InterpolatorType;
>
> TransformType::Pointer transform = TransformType::New();
> MetricType::Pointer metric = MetricType::New();
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
Those are type dependant name, shouldn't they require a 'typename'
before:
typename TransformType::Pointer transform = TransformType::New
();
typename MetricType::Pointer metric = MetricType::New();
typename InterpolatorType::Pointer interpolator = InterpolatorType::New
();
Yes I just realized that, wierd that it is allowed NOT to specify 'typename'
in VS while its mandatory in linux.
== 5 of 8 ==
Date: Wed, Sep 30 2009 4:14 am
From: Vladimir Jovic
fdm wrote:
>
> "Michael Doubez" <michael.doubez@free.fr> wrote in message
> news:d25e98ad-2ab6-41aa-a057-0a7cbedc5693@k19g2000yqc.googlegroups.com...
> On 30 sep, 12:39, "fdm" <f...@gk.com> wrote:
>> In a function I have:
>>
>> namespace Validation
>> {
>> template<typename T, typename M, typename I, typename R, typename P>
>> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
>> imageM, R & region, double & value) {
>> typedef T TransformType;
>> typedef M MetricType;
>> typedef I InterpolatorType;
>>
>> TransformType::Pointer transform = TransformType::New();
>> MetricType::Pointer metric = MetricType::New();
>> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>
> Those are type dependant name, shouldn't they require a 'typename'
> before:
> typename TransformType::Pointer transform = TransformType::New
> ();
> typename MetricType::Pointer metric = MetricType::New();
> typename InterpolatorType::Pointer interpolator = InterpolatorType::New
> ();
>
>
>
> Yes I just realized that, wierd that it is allowed NOT to specify
> 'typename' in VS while its mandatory in linux.
>
You got that wrong: it is required in c++
M$ got that wrong
== 6 of 8 ==
Date: Wed, Sep 30 2009 4:54 am
From: ytrembla@nyx.nyx.net (Yannick Tremblay)
In article <4ac33590$0$293$14726298@news.sunsite.dk>, fdm <fdm@gk.com> wrote:
>In a function I have:
>
>
>namespace Validation
>{
> template<typename T, typename M, typename I, typename R, typename P>
> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
>imageM, R & region, double & value) {
> typedef T TransformType;
> typedef M MetricType;
> typedef I InterpolatorType;
>
> TransformType::Pointer transform = TransformType::New();
> MetricType::Pointer metric = MetricType::New();
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>
>
>
>On windows vista 64 in Visual Studio this compiles fine. But in Ubuntu 9.04
>I get the error:
>
>compute_metric.h:22: error: expected `;' before 'transform'
>compute_metric.h:23: error: expected `;' before 'metric'
>compute_metric.h:24: error: expected `;' before 'interpolator'
>
>corresponding to the last three lines in the above code. I have made sure
>that inlcudes are setup correctly, any ideas?
>
>I have previously experienced that various statements are allowed in VS that
>is not allowed on Linux.
>
Sorry to be pedentic but what you are doing is NOT cross compilation.
It is simply compiling the same code using multiple compilers. Your
subject line is rather misleading.
Yannick
== 7 of 8 ==
Date: Wed, Sep 30 2009 5:34 am
From: Michael Doubez
On 30 sep, 13:14, Vladimir Jovic <vladasp...@gmail.com> wrote:
> fdm wrote:
>
> > "Michael Doubez" <michael.dou...@free.fr> wrote in message
> >news:d25e98ad-2ab6-41aa-a057-0a7cbedc5693@k19g2000yqc.googlegroups.com...
> > On 30 sep, 12:39, "fdm" <f...@gk.com> wrote:
> >> In a function I have:
>
> >> namespace Validation
> >> {
> >> template<typename T, typename M, typename I, typename R, typename P>
> >> void compute_metric(typename P::Pointer & imageF, typename P::Pointer &
> >> imageM, R & region, double & value) {
> >> typedef T TransformType;
> >> typedef M MetricType;
> >> typedef I InterpolatorType;
>
> >> TransformType::Pointer transform = TransformType::New();
> >> MetricType::Pointer metric = MetricType::New();
> >> InterpolatorType::Pointer interpolator = InterpolatorType::New();
>
> > Those are type dependant name, shouldn't they require a 'typename'
> > before:
> > typename TransformType::Pointer transform = TransformType::New
> > ();
> > typename MetricType::Pointer metric = MetricType::New();
> > typename InterpolatorType::Pointer interpolator = InterpolatorType::New
> > ();
>
> > Yes I just realized that, wierd that it is allowed NOT to specify
> > 'typename' in VS while its mandatory in linux.
>
> You got that wrong: it is required in c++
> M$ got that wrong
It is required by VC++ since Visual Studio 2003 (dixit msdn).
And for gcc, since version 3.4 which is not all that far away (April
18, 2004 from http://gcc.gnu.org/releases.html).
--
Michael
== 8 of 8 ==
Date: Wed, Sep 30 2009 6:20 am
From: Vladimir Jovic
Michael Doubez wrote:
> On 30 sep, 13:14, Vladimir Jovic <vladasp...@gmail.com> wrote:
>> You got that wrong: it is required in c++
>> M$ got that wrong
>
> It is required by VC++ since Visual Studio 2003 (dixit msdn).
> And for gcc, since version 3.4 which is not all that far away (April
> 18, 2004 from http://gcc.gnu.org/releases.html).
>
So, you are saying the OP is using previous a compiler from previous
century.
Both 2003 and 2004 were long time ago
--
Bolje je ziveti sto godina kao bogatun, nego jedan dan kao siromah!
==============================================================================
TOPIC: Pass a pointer variable to a function accept reference
http://groups.google.com/group/comp.lang.c++/t/330170d81fae3d1c?hl=en
==============================================================================
== 1 of 1 ==
Date: Wed, Sep 30 2009 4:14 am
From: pjb@informatimago.com (Pascal J. Bourguignon)
"Louis" <islouis@hotmail.com> writes:
> In my case passing pointer variable to function is the best using a
> pointer reference or a raw pointer?
It depends.
You seen, pointers and references are low level constructs.
There are several different parameter passing modes, that can be
explained in a higher level way:
- input parameters: The argument may be an expression (r-value).
Assigning to the parameter, inside the function,
has only a local effect, the value of the
expression cannot be changed.
- output parameters: The argument cannot be an expression (r-value),
only a place (l-value). The old value in that
place is not used, the function stores a new
value there.
Assigning to the parameter, inside the function,
will change the value of the argument place.
- inout parameters: The argument cannot be an expression (r-value),
only a place (l-value). The old value is used by
the function, and may be modified by the
function.
Assigning to the parameter, inside the function,
will change the value of the argument place.
When programming, you should first be concerned only by these
considerations.
Then, there are different mechanisms by which these parameter passing
modes may be implemented:
- argument passing by copy: the data is copied from the argument
to the parameter (input), or from the
parameter to the argument (output).
- argument passing by reference: a pointer to the data is copied from
the argument to the parameter
(input); the argument data is
accessed by dereferencing the pointer
parameter, and can thus be modified
(output).
- argument passing by name: this is a complex parameter passing
mechanisms that was used in some
early languages such as
Algol. Basically, the name of the
argument variable was in some way
passed to the parameter, and then
when using the parameter, it would
find the place by indexing the name
in the symbol table.
- etc.
In the case of C, the only mechanism is argument passing by copy. All
the arguments are expressions that are evaluated and whose value is
copied to the parameter.
Implementing an input parameter is therefore straigtforward, it's what
is normally done.
(CI)
void f(int inputParameter){ assert(inputParameter==42); inputParameter=0; }
f(24*2);
int i=42; f(i); assert(i==42);
int a[]={3,42,3}; f(a[1]); assert(a[1]==42);
To implement an inout parameter, we must use a pointer to the place:
C(IO)
void f(int* inoutParameter){ assert((*inoutParameter)==42); (*inputParameter)=0; }
f(&(24*2)); // ERROR! we cannot take a pointer of an expression.
int i=42; f(&(i)); assert(i==0);
int a[]={3,42,3}; f(&(a[1])); assert(a[1]==0);
To implement an output parameter, we must use a pointer to the place,
just like for an inout parameter, but we do not read the value of the
place in the function, before setting it:
C(O)
void f(int* outputParameter){ (*outputParameter)=0; }
f(&(24*2)); // ERROR! we cannot take a pointer of an expression.
int i; f(&(i)); assert(i==0);
int a[3]; f(&(a[1])); assert(a[1]==0);
However, in C there is a strange treatment of arrays: they're
considered as pointer to the first element when passed as arguments.
And old versions of the language could not copy structure arguments
(at least beyond a certain size) either. Also, considerations of
performance will make you seek another mechanism to pass big arguments.
For these cases, an input parameter can still be passed using a pointer:
void f(const int* inputParameter,int size){
if(1<size){
process(inputParameter[1]);
}
}
In modern C can also be written as:
void f(const int inputParameter[],int size){
if(1<size){
process(inputParameter[1]);
}
}
int a[]={1,2,3}; f(a,sizeof(a)/sizeof(a[0]));
/* equivalent to: */ f(&(a[0]),sizeof(a)/sizeof(a[0]));
For an inout or output array parameter, we would just drop the 'const'.
Now, in C++ we have in addition the references, and argument passing
by reference. We can use it to implement inout and output parameters:
Implementing an input parameter is the same as in C:
C++(I)
void f(int inputParameter){ assert(inputParameter==42); inputParameter=0; }
f(24*2);
int i=42; f(i); assert(i==42);
int a[]={3,42,3}; f(a[1]); assert(a[1]==42);
To implement an inout parameter, we may use a reference to the place:
C++(IO)
void f(int& inoutParameter){ assert(inoutParameter==42); inputParameter=0; }
f(24*2); // ERROR! we cannot take a refernece of an expression.
int i=42; f(i); assert(i==0);
int a[]={3,42,3}; f(a[1]); assert(a[1]==0);
To implement an output parameter, we must use a pointer to the place,
just like for an inout parameter, but we do not read the value of the
place in the function, before setting it:
C++(O)
void f(int& outputParameter){ outputParameter=0; }
f(24*2); // ERROR! we cannot take a pointer of an expression.
int i; f(i); assert(i==0);
int a[3]; f(a[1]); assert(a[1]==0);
In C++, we still have the same problem with array, that are passed by
copy of a pointer to the first element by default, but we can now use
passing by reference:
typedef int Vector[3];
void f(const vector& inputParameter){
assert(inputParameter[1]==2);
inputParameter[1]=0;
}
int a[]={1,2,3}; f(a); assert(a[1]==0);
(and drop 'const' for inout and output parameters).
For structures there's no more size restriction for passing by copy,
but you might still want to use a reference there, to avoid copying
big structures.
In the case of a structure such as std::vector<int>, you may pass it
by copy, since it's really a small structure (usually 3 words), and
passing this structure by copy won't copy the elements in the vector.
A last word, compare the call sites in C++(I) and C++(IO) above:
int i=42; f(i); assert(i==42);
int i=42; f(i); assert(i==0);
It may look surprizing that in one case i is not changed (and couldn't
be changed), while in the other case, i can be changed. When reading
the call site alone, no syntax clues us about this difference. For
this reason, some C++ programmers prefer to keep using pointers for
inout and output parameters, see C(IO):
int i=42; f(&(i)); assert(i==0);
My own point of view is that (1) the name of the function should clue
you:
int salary=42; setSalary(salary); assert(salary==42);
int taxes; getTaxes(taxes); assert(taxes==0);
so that you can still use references, without any loss of readability,
and (2) you should avoid using inout and output parameters anyways,
and rather use a functional programming style, where you have only
input parameter and use results:
int salary=42; setSalary(salary); assert(salary==42);
int taxes; taxes=getTaxes(); assert(taxes==0);
> In my case passing pointer variable to function is the best using a
> pointer reference or a raw pointer?
So to answer your questions, it depends on whether the parameter is an
input, inout or output parameter. A pointer is small (one word), so
as an input parameter you can pass it by copy:
typedef int* intp;
void f(intp inputParameter);
int i=42; f(&i);
intp p=&i; f(p); assert(p==&i);
In the case of an inout or output parameter, if you choose to have a
call place hint that your pointer may be modified, you'd use a pointer
to the pointer:
typedef int* intp;
int k=24;
void f(intp* outputParameter){ (*outputParameter)=&k; }
intp p=0; f(&p); assert(p==&k);
If you choose better function names, you can use a reference:
typedef int* intp;
int k=24;
void getPointerToIntStorage(intp& outputParameter){ outputParameter=&k; }
intp p=0; getPointerToIntStorage(p); assert(p==&k);
> > The difference is that take_a_raw_pointer will accept temporary
> > pointers returned by functions, while take_a_pointer_reference will
> > want a pointer variable.
>
> still a bit confuse
> do u mean using raw pointer, temp will modify the same address where d
> pointing to?
> while using pointer reference, temp will modify the reference of d...?
What I mean here is that take_a_raw_pointer takes a r-value
(expressions), while take_a_pointer_reference takes a l-value
(places).
--
__Pascal Bourguignon__
==============================================================================
TOPIC: using local static variable inside a function
http://groups.google.com/group/comp.lang.c++/t/7d53e8ea36d0502c?hl=en
==============================================================================
== 1 of 3 ==
Date: Wed, Sep 30 2009 5:23 am
From: "subramanian100in@yahoo.com, India"
Is it advisable to use a local static variable inside a function ? I
want to know whether there are any drawbacks of using local static
variable inside a function.
Kindly explain.
Thanks
V.Subramanian
== 2 of 3 ==
Date: Wed, Sep 30 2009 5:28 am
From: Victor Bazarov
subramanian100in@yahoo.com, India wrote:
> Is it advisable to use a local static variable inside a function ?
Yes. No. Maybe.
> I
> want to know whether there are any drawbacks of using local static
> variable inside a function.
Drawbacks? I am not sure I understand the question. A static variable
is what it is - a static variable. Its use has the same drawbacks as
with any other static variable. But why would you think of the
drawbacks beforehand? Use what's needed. If you need a static
variable, use it. If you don't need a static variable, don't use it.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
== 3 of 3 ==
Date: Wed, Sep 30 2009 7:02 am
From: "AnonMail2005@gmail.com"
On Sep 30, 8:23 am, "subramanian10...@yahoo.com, India"
<subramanian10...@yahoo.com> wrote:
> Is it advisable to use a local static variable inside a function ? I
> want to know whether there are any drawbacks of using local static
> variable inside a function.
>
> Kindly explain.
>
> Thanks
> V.Subramanian
A static variable inside a function can sometimes be a good idea. A
Meyers singleton is a good example of the use of a static variable
inside a function.
But, and this is a big one, once you move from single threaded apps,
any static variables inside a function run into initialization issues
if more than one thread calls the function.
Static variable inside a function have compiler generated code that
makes sure the object is only constructed and initialized once. Since
standard C++ knows nothing about threads, the mechanism used to ensure
this is not thread safe.
HTH
==============================================================================
You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.
To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en
To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com
To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en
To report abuse, send email explaining the problem to abuse@googlegroups.com
==============================================================================
Google Groups: http://groups.google.com/?hl=en
No comments:
Post a Comment