|
Is there any easy way to shift or swap elements inside vector?
For example if I have a vector that contains:
A B C D E F
and I want to swap elements B and C to read
A C B D E F
Thanks in advance!
-Rob
Whoever said nothing is impossible never tried slamming a revolving door!
|
|
|
|
|
|
Perfect.
Thank you!
Whoever said nothing is impossible never tried slamming a revolving door!
|
|
|
|
|
Hi there,
I am using VS 2008 Standard and have a problem compiling the following small C++ code snippet:
template <typename ArrayElement>
class Array
{
public:
virtual void split( Array<Array*> *result = 0)
{
if( result != 0)
{
result->clear();
}
}
void clear()
{
}
};
void main(void)
{
Array<int> a;
a.split();
}
The code itself here does not do anything really useful as it has been simplified to demonstrate the nature of problem which occurs with my real Array implementation: the code does not compile!! And I really can't understand why?? Some kind of recursion in evaluating the template seems to happen here. BUT: Note the underlined "virtual" keyword in the code above. Leave this away and suddenly the code compiles?!? This does not make sense to me - what has the successful compilation to do with "virtual" functions in this case??
For my "real" Array class I must be able to have all the member functions virtual to overrride them in derived classes. So the solution can't be to just leave the functions non-virtual. Additionally the data type shown here ( Array<Array*> ) for the restult of the "split" method shall not be changed as this data type seems to make a lot of sense in my mind. The returned data is also an array - an array of arrays to be exact.
So WTF can I do to make this work? Any help is really really appreciated
Thanks,
Oli
|
|
|
|
|
|
(nevermind)
modified on Friday, September 4, 2009 12:23 AM
|
|
|
|
|
The problem mentioned in the links is different from the OP here.
The links talk about a template member function.
The OP talks about a virtual member function of a template class.
That is perfectly valid.
Try making the clear function virtual.
virtual void clear()
This works perfectly.
I'm curious about the syntax of the function
virtual void split( Array<Array*> *result = 0)
What is the intention of declaring the parameter as Array<Array*> ?
There must be a better way of doing this.
Incidently changing this to something like Array<int*> does compile.
I'm not sure why the code compiles when omitting the virtual keyword in the original code.
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
«_Superman_» wrote: Try making the clear function virtual.
virtual void clear()
By changing the function member "clear" to "virtual" the compiler still generates code until infinity. So I can't see any difference here. Btw: In my "real" implementation "clear" exists and IS virtual.
«_Superman_» wrote: I'm curious about the syntax of the function
virtual void split( Array<array*> *result = 0)
What is the intention of declaring the parameter as Array<array*>?
There must be a better way of doing this.
Well the "split" functions takes the original Array (*this) and generates several sub arrays of the same type from it. These resulting arrays shall then be returned als as an array of arrays. That's the meaning of this param. In my original implementation however there are several more parameters which define how to split the array and the result param is declared as "Array<Array*> &result" as I do not allow to provide no result container. For this synthetic code demo I have changed a few things compared to my "real" implementation which have nothing to do with the compile problem but help to review the issue.
As you can see I want to consistently use Array wherever possible as everything shall be usable in the same way.
|
|
|
|
|
The issue is the call to clear, not the existence of split...which makes me think that VC++ is being eager in instantiating virtual methods - I'm guessing it's a slight bug in VC++ as g++ compiles your code quite happily..
See, when VC++ instantiates the call to clear , it needs to instantiate the template class Array<Array<ArrayElement>*> . It wants a vtable for that class, so it'll need an instantiation of split for that class. While instantiating split, it'll need to instantiate the call to clear , so it'll instantiate the class Array<Array<Array<ArrayElement>*>*> ....
And so on, ad infinitum...
I think this is demonstrable by changing clear() to be
void clear()
{
split();
}
g++ won't compile this, giving an error message very similar to the VC++ warnings you were getting.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Stuart Dootson wrote: See, when VC++ instantiates the call to clear, it needs to instantiate the template class Array<array<arrayelement>*>. It wants a vtable for that class, so it'll need an instantiation of split for that class. While instantiating split, it'll need to instantiate the call to clear, so it'll instantiate the class Array<array<array<arrayelement>*>*>....
And so on, ad infinitum...
Yes, I totally agree with you here and already knew that this happens. But it makes no sense to me as the compiler should only generate code that is USED. The code that the compiler generates here is not used anywhere - it COULD be used but it's not. Leave away the "virtual" keyword and suddenly it compiles without problems. Thinking of it I see no difference between the two versions as the compiler could also generate code until infinity without the "virtual" keyword. For me it seems like a VS 2008 compiler specific issue and I will certainly try the GCC compiler soon. (Must prepare my full project for that however.)
Stuart Dootson wrote: void clear()
{
split();
}
g++ won't compile this, giving an error message very similar to the VC++ warnings you were getting.
Err, what you are doing here is an OBVIOUS recursion that could not even be executed without stack overflow The one in my code example isn't. What it's really about is code generation that does take place although the generated code is not actually needed. I will certainly never ever use a Array<Array<Array<Array<Array<Array<Array<Array<ArrayElement>...> container ANYWHERE So why does the compiler think I will?
|
|
|
|
|
o.kauert wrote: But it makes no sense to me as the compiler should only generate code that is USED.
VC++ has historically had issues with instantiating more than it necessarily needed with templates.
o.kauert wrote: Err, what you are doing here is an OBVIOUS recursion that could not even be executed without stack overflow
Yes it could be executed. The condition within split (if (result != 0) ) will terminate recursion at run-time. However, the compiler cannot reliably and economically perform the static analysis required to see that and know that the first call to split from clear will terminate the recursion, meaning it doesn't need an instantiation of clear to be called at that point.
o.kauert wrote: What it's really about is code generation that does take place although the generated code is not actually needed. I will certainly never ever use a Array<Array<Array<Array<Array<Array<Array<Array<ArrayElement>...> container ANYWHERE So why does the compiler think I will?
Because it's unable to see as far as you - it doesn't have the knowledge of your design intent. It has to follow pre-defined rules about what to instantiate.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Stuart Dootson wrote: o.kauert wrote:
What it's really about is code generation that does take place although the generated code is not actually needed. I will certainly never ever use a Array<array<array<array<array<array<array<array<arrayelement>...> container ANYWHERE So why does the compiler think I will?
Because it's unable to see as far as you - it doesn't have the knowledge of your design intent. It has to follow pre-defined rules about what to instantiate.
Sure, I agree with you and I know that the compiler behaves rule based all the time. But the implemented rule set of the MS compiler seems to not match the sensible reality in this case and as one can see the compiler does not even notice that there is an unresolvable issue for the way it operates here.
This COULD be solved however I think - given another compiler I will soon try GCC and see what happens.
|
|
|
|
|
o.kauert wrote: I will soon try GCC and see what happens.
Oh, your code compiles fine with gcc. I tried that pretty much first, as I suspected a VC++-specific issue.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Stuart Dootson wrote: Oh, your code compiles fine with gcc. I tried that pretty much first, as I suspected a VC++-specific issue.
That's good So maybe I should start my next question... How can I REPLACE the VC++ compiler with the gcc counterparts within the VS IDE? I want to fully use the gcc toolchain and not the MS compiler, linker etc.
So is it possible to fully replace the tools and still get errors, warnings etc. in the VS IDE ( the message text is of course then coming from the gcc counterparts)? Also debugging should still be possible in the VS IDE. This would be really great! Any hints? Thanks
|
|
|
|
|
That's not so do-able The VS IDE wouldn't correctly parse errors coming out of gcc, as they're different formats, and also the gcc debug format is completely different than the VC++ one - neither WInDbg nor Visual Studio can debug code produced by gcc. Also, I don't think you can build against MS libraries like MFC and ATL with gcc.
Alternatives? Eclipse CDT[^] and Dev-C++[^] are both IDEs using gcc. Also, I believe the Intel C++ compiler can be used as a drop-in replacement for MSVC, but that costs money
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
The need to compile wav files into a Doc/View plus modeless dialog MFC program led to abandoning a functioning mechanism to play random wav files:
PlaySound("m_sStrConcatenatedStringWithPath",NULL,SND_FILENAME|SND_SYNC);
(where sStrConcatenatedStringWithPath = “/path/201.wav” etc.)
and adopting:
LPTSTR pRandomSound = m_sStrConcatenatedStringResource.GetBuffer(0);
PlaySound(MAKEINTRESOURCE, pRandomSound, GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE);
m_sStrConcatenatedStringResource.ReleaseBuffer(0);
(where m_sStrConcatenatedStringResource = “IDR_WAVE_201” etc.).
...that fails to play the wav files even when...
PlaySound(MAKEINTRESOURCE, IDR_WAVE_201, GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE);
will play the IDR_WAVE_201 resource.
Many attempts experimenting different ways to cast the CString to the LPTSTR and obtaining the handle to the executable led to the code above, which still will not play the random sound resource.
Suggestions?
"For a successful technology, reality must take precedence over public relations, for nature cannot be fooled." Richard Feynman, Minority Report to the Official Report on the Space Shuttle Challenger Crash
|
|
|
|
|
lctrncs wrote: PlaySound(MAKEINTRESOURCE, pRandomSound, GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE);
What PlaySound() are you using that takes four arguments?
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
Thank you for responding.
BOOL PlaySound(
LPCSTR pszSound,
HMODULE fdwSound,
DWORD fdwSound)
There are two arguments:
LPCSTR (pszSound) and HMODULE (fdwSound)
pRandomSound and GetModuleHandle(NULL)
and two flags:
DWORD fdwSound
SND_SYNC|SND_RESOURCE
Thanks again. I hope this answers your question.
"For a successful technology, reality must take precedence over public relations, for nature cannot be fooled." Richard Feynman, Minority Report to the Official Report on the Space Shuttle Challenger Crash
|
|
|
|
|
lctrncs wrote: BOOL PlaySound(
LPCSTR pszSound,
HMODULE fdwSound,
DWORD fdwSound)
There are two arguments:
LPCSTR (pszSound) and HMODULE (fdwSound)
pRandomSound and GetModuleHandle(NULL)
and two flags:
DWORD fdwSound
SND_SYNC|SND_RESOURCE
You seem to be confused. Look at the code snippet in your original post. You are passing PlaySound() four arguments: 1) MAKEINTRESOURCE , 2) pRandomSound , 3) GetModuleHandle(NULL) , and 4) SND_SYNC|SND_RESOURCE .
So my question still remains: where does this four-argument function come from? The answer to this may end up having no bearing on the actual problem, but if you can't post a working code snippet, it's kind of hard to come up with a useful answer.
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
The
BOOL PlaySound(
LPCSTR pszSound,
HMODULE fdwSound,
DWORD fdwSound)
comes from the "Multimedia: Platform SDK" section of the Visual C++ 6.0 MSDEV documentation.
This specific use of the MAKEINTRESOURCE macro is documented in the "Technical Articles" section of the Visual C++ 6.0 MSDEV documentation in a file called "Moving Your Game to Windows, Part III.
Does this answer you question?
"For a successful technology, reality must take precedence over public relations, for nature cannot be fooled." Richard Feynman, Minority Report to the Official Report on the Space Shuttle Challenger Crash
|
|
|
|
|
When You add WAV resource by ID there is no way to call PlaySound (and other resource functions) by resource name and vice versa - when you add resource with resource name string - You can not access resource by it' ID.
For this resource script file:
#define SOUND_1
...
SOUND_1 WAV "snd1.wav"
"MOO" WAV "moo.wav"
Valid PlaySound call is:
PlaySound(MAKEINTRESOURCE(SOUND_1), ...);
PlaySound("MOO", ...);
|
|
|
|
|
Thanks to everyone at CodeProject!
It appears that the original post may not be clear.
Therefore, consider the following code snippet which includes much more information about the problem and the (failed) attemtps to resolve it.
Again, for reasons this beginner has yet to understand, PlaySound works fine with a filename constructed from a CString and a random number (/path/filename1.wav), but fails when concatenated CStrings are used to create a resouce identifier (IDR_WAVE_1).
Please consider the code and coments below.
int m_nRandomSound;
m_nRandomSound = getrandom( 500, 509 );
CString m_sStrRandomSound;
m_sStrRandomSound = "";
CString m_sStrRandomResourcePrefix;
m_sStrRandomResourcePrefix = "IDR_WAVE_";
m_sStrRandomSound.Format("%d", m_nRandomSound);
CString m_sStrRandomResourcePrefixWav;
m_sStrRandomResourcePrefixWav = m_sStrRandomResourcePrefix + m_sStrRandomSound;
CString m_sStrRandomResourcePrefixWav2;
m_sStrRandomResourcePrefixWav2="IDR_WAVE_503";
PlaySound(m_sStrRandomSoundPathWav, GetModuleHandle(NULL), SND_FILENAME|SND_SYNC );
PlaySound(MAKEINTRESOURCE(IDR_WAVE_503), GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE );
PlaySound(m_sStrRandomResourcePrefixWav2, GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE );
PlaySound("m_sStrRandomResourcePrefixWav", GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE );
LPCTSTR pRandomSound = m_sStrRandomResourcePrefixWav.GetBuffer(0);
LPCTSTR pRandomSound2 = m_sStrRandomResourcePrefixWav2.GetBuffer(0);
PlaySound(MAKEINTRESOURCE(pRandomSound2), GetModuleHandle(NULL), SND_SYNC|SND_RESOURCE );
PlaySound(MAKEINTRESOURCE(pRandomSound), AfxGetResourceHandle(), SND_SYNC|SND_RESOURCE );
PlayWav(pRandomSound);
m_sStrRandomResourcePrefixWav.ReleaseBuffer();
m_sStrRandomResourcePrefixWav2.ReleaseBuffer();
Thank you again.
Your comments and suggestions are greatly appreciated.
"For a successful technology, reality must take precedence over public relations, for nature cannot be fooled." Richard Feynman, Minority Report to the Official Report on the Space Shuttle Challenger Crash
|
|
|
|
|
Hi All
How to create detailed log.txt file in C programming.
As of now am using
fp=fopen("log.txt","a");
fprintf(fp, "Input string = %s\n", Work);
But i want to write log file with much details which is help me to debug.Please gimme me if any prebuild code or related link.
Thanks,
Mohan.T
Mohan t working for N.I.C
|
|
|
|
|
You can use of WriteFile .
Of one Essence is the human race
thus has Creation put the base
One Limb impacted is sufficient
For all Others to feel the Mace
(Saadi )
|
|
|
|
|
In C (assuming you are really programming in pure C), you will probably not find that much code for that (I tried a few google, and found nothing usefull)
But it should be quite simple to do.
Declare a few global functions that will open the file write to the file, close the file...
What you put in the file is really up to you; no tool will completly do what you want.
If you are looking for C++ code there are some example here, on CP (for example :
Advanced Logging for all kind of applications[^] )
This signature was proudly tested on animals.
|
|
|
|
|