|
If you are still looking for an answer, I posted an article explaining this just today.
http://www.codeproject.com/Articles/236927/All-your-base64-are-different-to-us
In short, there is a way, provided you know all template types you will be using. I'll copy the example I had in the article here:
-------------------------------------
-- In my_template.h file
...
template <typename T>
T my_temp_func(const T& t);
-------------------------------------
-- In my_template.cpp file
#include "my_template.h"
template <typename T>
T my_temp_func(const T& t)
{
return t;
}
int my_temp_func<int>(const int& t);
-------------------------------------
-- In using_my_template.cpp
#include "my_template.h"
...
int i = my_temp_func<int>(4); string s = my_temp_func<string>("Abob");
In the example above, the declaration in the last line of my_template.cpp tells the compiler there’ll be a variant of the template function that uses int as template parameter. Okay, says the compiler, I’ll put an inline copy there. Since the generic definition is right there in the same compilation unit (ie my_template.cpp), this is something the compiler can do – it has all the information it needs.
The result of that is that in the compiled file (probably called my_template.obj) there is now a function that has the signature int my_temp_func(const int& t). This is a fully defined specialisation of a template function, so to the linker it looks just like a normal function.
However, the linker won’t be able to find a string specialisation, so this will generate a linker error.
In
|
|
|
|
|
Templates behave a lot like inline functions. The entire implementation is required to be declared in the include file for the compiler to use it correctly.
I believe you have described this method in your question, but I would like to start here, because it is the method I prefer if I dont want a single .h file implementation. I will use the file name Tmp.x for all of the examples, where x is the extension.
1) You declare all of your template classes and functions in your file Tmp.h .
2) Then implement all of the functions in a separate file with an extension such as Tmp.inl (inline). It is important that when the function definitions appear outside of the class definition, that you declare each function declaration with inline. Otherwise if you include this header file in multiple places, you will get linker errors for duplicate symbols.
3) At the bottom of Tmp.h and the line #include "Tmp.inl". The file implemented in step 2.
If you prefer to have the file extension to still be .cpp, you can use that as well. You would follow all of the steps the same way, and include the .cpp file at the end of the .h file. The only difference, in your Visual Studio project, you will have to change the settings for the file so that it does not get compiled like the other .cpp files. It is already included in a header file.
You cannot get around having the Template implementation available to the compiler when it sees the first usage of the template.
Why? Because that is the point where the compiler generates the actual code from the template.
Originally there was supposed to be a keyword "export" to allow the templates to be defined like regular classes, but that never became part of the standard, and therefore is not available.
Hopefully this helps.
|
|
|
|
|
thanks a lot,
it was really helpful
hrishi
|
|
|
|
|
Your basic problem appears to be to understand how Header Files, cpp Files, the Compiler and the Linker work.
First the Compiler. The Compiler builds an Object File. This is a Binary representation of a cpp File. It containd the CPP Code you wrote, converted to machine code as well as a whole raft of information needed later. The Compiler contains a thing, called a Pre-Processor. It prepares your CPP file before actual compilation. Conceptually it produces a New Source File. It copies your file Line by Line. but if it finds a statement like #include "MyBeautifulHdr.h", it does not copy the include statement, but, instead writes the entire contents of "MyBeautifulHdr.h" at the location of the '#include' statement. When it encounters a #define FOO 1 statement, it undertakes to replace henceforth every future occurrence of 'FOO' with 1. It goes on like that at infinitum, and the final file offered to the compiler has all '#includes, #defines, #if's etc resolved.
At that stage the compiler does not know ( and does not care) from what file what item came from, (except for error reporting). It just builds the Object File, (if it Can)
if it cannot, you get an error.
Each of the Object Files generated roughly correspond to the code you wrote in a cpp file.
An extern declaration is a promise to the compiler that somewhere in an other file or library, an item of that specification exists.
The Linker tries to build an executable out of all those object files. In doing so, it may also include Object files written by others, e.g. those written by Microsoft, which came with your compiler package. To make that process more efficient, multiple obj files can be gathered together into a library (.lib) file
If the linker cannot find a named item, or, finds more than one, the linker will fail building the executable.
Getting a Full understanding of how your tools work will answer your queery.
regards,
Bram van Kampen
|
|
|
|
|
I have this benchmark program that started off as a console program and I am now well into making work with a window instead. It's all Win32 for the most part with a smattering of C++ STL for some containers.
I launch the background via a keyboard command ctrl-r
case (0x52):
if(GetKeyState(VK_LCONTROL) || GetKeyState(VK_RCONTROL)) {
_beginthread(showtime, NULL, NULL);
}
break;
So what am I doing wrong, the background thread runs for while but crashes, used to work fine.
http://www.contract-developer.tk
|
|
|
|
|
What is it the background thread doing? Do you get an exception or any other information when it crashes?
The best things in life are not things.
|
|
|
|
|
void showtime(void *dummy) {
computing = true;
output.clear();
output = _TEXT("Fibonacci 3.0.0 for Windows");
output += ToString("/n/l/n/l");
output += _TEXT("(c) 2010-1 583727 BC Ltd, All Rights Reserved.");
output += _TEXT("/n/l");
output += _TEXT("Free for peronsal use only");
output += _TEXT("/n/l/n/l");
output += _TEXT("Commercial and government use requires a license");
output += _TEXT("/n/l/n/l");
output += _TEXT("To acheieve consistant results, run this program in the clean boot mode");
output += _TEXT("/n/l");
output += _TEXT("Click on start, in the seach box enter 'msconfig' and choose the startup tab, disable everyting and reboot");
output += _TEXT("/n/l/n/l");
output += _TEXT("RAM Performance ");
output += ToString(benchmark(fib2));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Scalar Performance ");
output += ToString(benchmark(fib3));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("CPU Large Multiplication Performance ");
output += ToString(benchmark(fib4));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
v.resize(0); t.resize(0);
output += _TEXT("Recursive Factorial Performance ");
output += ToString(benchmark(RunFact));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Bubble Sort Performance ");
output += ToString(benchmark(RunBubbleSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Insertion Sort Performance ");
output += ToString(benchmark(RunInsertionSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Shell Sort Performance ");
output += ToString(benchmark(RunShellSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Quick Sort Performance ");
output += ToString(benchmark(RunQuickSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Merge Sort Performance ");
output += ToString(benchmark(RunMergeSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Heap Sort Performance ");
output += ToString(benchmark(RunHeapSort));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel Bitwise Sieve of Eratosthenes Performance ");
output += ToString(benchmark(sieve));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel Goldbach Conjecture Performance Performance ");
output += ToString(benchmark(goldbach));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel Collatz Conjecture Performance ");
output += ToString(benchmark(RunCollatz));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel vector<float> normalization ");
output += ToString(benchmark(vtestfloat));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel vector<double> normalization ");
output += ToString(benchmark(vtestdouble));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel vector<std::complex> normalization ");
output += ToString(benchmark(vtestcomplex));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel matrix<float> multiplication ");
output += ToString(benchmark(mtest1));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel matrix<double> multiplication ");
output += ToString(benchmark(mtest2));
output += _TEXT(" seconds");
output += _TEXT("/n/l");
output += _TEXT("Parallel matrix<std::complex> multiplication ");
output += ToString(benchmark(mtest3));
output += _TEXT(" seconds");
output += _TEXT("/n/l/n/l");
computing = false;
MessageBox(NULL, L"Completed", L"Fibonacci", MB_OK);
}
http://www.contract-developer.tk
|
|
|
|
|
What is output and why are you putting so much text into it for no apparent reason?
The best things in life are not things.
|
|
|
|
|
typedef std::basic_string<wchar_t> tstring;
tstring output;
The output will eventually be placed on the clipboard as a text
http://www.contract-developer.tk
|
|
|
|
|
You have still given no information as to where this crashes, and what exceptions or other diagnostic information you see. We cannot guess what happens on your system; have you tried running it through the debugger?
The best things in life are not things.
|
|
|
|
|
I am going to use MessageBox all over the module and see how far it gets.
One question, do I need to use the exitthread anywhere?
http://www.contract-developer.tk
|
|
|
|
|
VeganFanatic wrote: do I need to use the exitthread anywhere?
Impossible to say; it depends what your program is actually trying to do. Are you sure you need multiple threads?
The best things in life are not things.
|
|
|
|
|
Putting that module into a thread was to make the program able to quit at any time.
This was to make sure the message handler is able to get messages.
http://www.contract-developer.tk
|
|
|
|
|
From looking at the code you posted, its probably because another thread accesses or destroys output while the thread is still using it. The way you're using the string is also very bad practice since you're forcing it to reallocate memory constantly for the string and this is very inefficient. Why not get all the information you need once, then allocate/format your string? This would allow the thread to run way faster and more efficiently.
|
|
|
|
|
When you have this run on one thread, does it complete properly?
I would do 3 things to trouble shoot and improve the code:
1) Add another command to your console entry, that allows you to start the "showtime" function, and run it one the same thread. Verify that it functions properly.
2) Enable Exceptions. I assume you are using Visual Studio of some sort, if not you will have to figure out how to do this for your debugger. In Visual Studio you can do this at the Debug | Exceptions Menu. Enable: C++ Exceptions, Native Run-Time Checks and Win32 Exceptions.
When you run your application in the debugger and it crashes, you will be right at the point in code the exception is thrown. Then you can look at the stack and all of the other helpful information.
3) Break up all of the work done in "showtime" into a smaller pieces. Probably a common function that prints out the basic text and runs the test you initiate. Then in "showtime" you would make multiple calls to your smaller function. This will help make your code more manageable.
From looking at your code, my guess is that one of the test routines is returning a NULL or some value that the string functions dont like, or is failing internally.
|
|
|
|
|
Hello all,
Could anyone please give me a efficient method and suggestions for the following.
I have many classes already in my VC++ project, which were build on MFC. Meaning the data types were MFC based. like CByteArray, CString etc etc. Now I need to avoid the uses of MFC data types , and introduce STL data types.
could you please give me an efficient and less time consuming method to migrate the same. For eg: shal I use my own classes to mimic MFC classes like CString. or correct each uses/mehtod of MFC classes wherver there is, and change with STL based methods.... I am a bit confuse. please suggest me
thanks in advance
Hrishi
|
|
|
|
|
Hi Hrishi,
hrishi321 wrote: I have many classes already in my VC++ project, which were build on MFC. Meaning
the data types were MFC based. like CByteArray, CString etc etc. Now I need to
avoid the uses of MFC data types , and introduce STL data types.
As MFC internally uses its own collection and string classes, you will increase your code footprint, and keep dependancy on all MFC classes and data types.
Anyhow you can use CStdString [^] as drop-in replacement for CString , and you should write your own CStdByteArray etc.. based on STL collections and exposing the same interface as the matching MFC collections. It could be an interesting CodeProject article
Good luck!
AR
When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)
|
|
|
|
|
Thank you so much for your kind suggestion.
I already started my implementation. Thought I am sure, I will have small doubts on my path.
As a starter, I am trying to implement the CBytearray, Could you please tell me, whether do I need to implement FreeExtra() method of MFC CBytearray, in my stl:: vector? . Is there any methods to mimic this? Or actually STL tales care of it own?
|
|
|
|
|
Hi,
If your compiler supports C++2011 (VC2010 or gcc 4.5) std::vector::shrink_to_fit() is the functional equivalent to CByteArray::FreeExtra(). If you are on C++2003 use v.reserve(v.size()) to achieve the same goal.
cheers,
AR
When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)
|
|
|
|
|
There's A LOT that goes into writing a framework, so you certainly don't want to write your own replacement classes. Depending on how much of the project is MFC based, you may have issues trying to replace with only STL calls. Some concepts don't exactly translate well, for example, what is a CDialog (the base for creating dialogs in MFC)? Well, its a bunch of WinAPI calls that create windows, configure properties, and act as a container for code within the dialog. How would you replicate that with STL alone? You can, but its a lot of work, STL is not exactly a framework that comes equipped as an MFC replacement (or replacement for any type of framework for that matter).
|
|
|
|
|
thanks for your suggestion. After doing a small research and checking the amount of use of the MFC types, I have decided to implement the MFC types, whichever are in my project, and of-course not all methods but eh necessary ones.
I will have many doubts during this course of time, Hope to keep getting advices from you
thanks
hrishi
|
|
|
|
|
Why do you want to do that! Horses for Courses.
Do you also want to migrate from Exel to Word?
Regards,
Bram van Kampen
|
|
|
|
|
I have this code below that updates a dbf file now this code before also updates a cdx file but I changed something in the values I added now the cdx file is not inline with the dbf.
I have tried to "reindex" and "SET INDEX TO" however everytime I do an insert in the dbf table the modified date of the cdx file stays the same as the old one.
Should the cdx be updated everytime there is something new inserted?
DIAGNOSTICS_CHECKPOINT;
LOG(L"AutoLoad File Connection String");
LOG(this->_connectionstring.c_str());
cnn->CursorLocation = adUseClient;
try { hr = cnn->Open(this->_connectionstring.c_str(), L"", L"", 0); }
catch (_com_error& e)
{ wss.str(L"");
wss << L"Opening the AutoloadFile connection from '"
<< _connectionstring.c_str()
<< L"' has failed (COM Error: " << e.ErrorMessage()
<< L", " << hr << L")."
<< std::endl;
LOG(wss.str().c_str());
throw;
}
DIAGNOSTICS_CHECKPOINT;
wss.str(L"");
wss << L"INSERT INTO "
<< this->_tablename
<< L" VALUES ('"
<< trans_id << L"','"
<< params << L"','"
<< status << L"',"
<< rec_no << L")"
;
DIAGNOSTICS_CHECKPOINT;
std::wstring sql(wss.str().c_str());
LOG(L"Executing INSERT into the autoload file");
LOG(sql.c_str());
try
{ rs->Open(sql.c_str(), cnn.GetInterfacePtr(),
adOpenForwardOnly, adLockReadOnly, adCmdText);
}
catch (_com_error& e)
{ wss.str(L"");
wss << L"Executing SQL statement:\n"
<< sql.c_str()
<< L"'\n...has failed (COM Error: "
<< e.Error() << L", '"
<< e.ErrorMessage()
<< L"')."
<< std::endl;
LOG(wss.str().c_str());
throw;
}
|
|
|
|
|
Hi All
I am working on a localization project.
I am trying to localize the Tool tips of the Tool bar buttons that are coming in English.
Tool tips are specified in the resource as direct strings in the prompt field of the properties.
Can you please advice me on how to refer the strings from String Table instead.
Any help is appreciated.
Thanks in advance.
Selva
|
|
|
|
|
Insert new 'String Table' resource. Add your strings to it. Use LoadString function to get the strings.
|
|
|
|
|