mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

at lines 70 and 75, remove the "const char" part, it is not valid C++ syntax.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm not sure I understand what you mean with the whole interpreted language application stuff.

But, all you need to make that little snippet of code work is to forward-declare the types. Specifically, you can add the following at the very beginning of the code you posted:

class b; //forward-declaration of class b.

And your code will compile just fine.

I don't know if that solves your real problem, but it answers the question you asked.

fishsicles commented: Thanks for the forward-declaration aid! +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

That's much much worse than the first program you posted. I mean, the first program is fine. It works except for that tiny one-line mistake. The code you just posted now is far from even compiling.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

May I suggest that you read the following explanation.

One solution to your problem is explicit instantiation of the template. Here is an example of a function template. This is, of course, only applicable if you have a reasonably small amount of predetermined types for which your template could be instantiated. In real-life, this technique will make the compilation of the template code take a very long time, but it will make all the code that use that template code very fast to compile.

mitrious commented: Offered a pretty complete solution and really useful info +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>// Am I right to pass it just by its name? Will the constructor know its name?
No. Inside the body of a member function, the object itself is accessible via the "this" pointer. This is a pointer to the instance of the class that was attached to the call to the member function. To turn that pointer to a value or reference, you just need the dereferencing operator, as such:

TheData::TheData()
{
	Valid = false;
	Length = 0;
	Values = 0;
	TheMenu::MainMenu(*this); // *this dereferences the this pointer to make it a reference (or value).
}

>>// I can still use the same name right?
Yes. Because DataIn from main() is only visible in the main() function, there is no problem in reusing the same name as the parameter name. In fact, if it is a good name that describes the purpose of the variable, then it is preferable that you use that name for the parameter. But, it does not have to be the same name, it can be any name that you want and the name you choose in the definition of the function is the name that you need to use to use that parameter within that function.

>>// This little bit, does that create a class object called DataOut?
Yes. That creates a global object of class TheData with the name DataOut. Since it is global, it is accessible anywhere. This is ok, but considered bad programming practice (both the …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I thought that because main() doesn't end yet, all the members and variables that were created inside it would still be available to all the other functions in the program.

You're logic is correct but there is another aspect that you are neglecting. Yes, variables that you declare in main are available as long as main has not finished (and that would be true for any function or { } block). However, the variables declared in the main function are not _visible_ or _accessible_ to any other parts of the program besides the main function. Visibility of variables have to be limited, otherwise it would be horribly difficult to make sure that you refer to the correct variables and also it introduces an crazy mix between the caller and callee contexts.

If you want access to a variable in a function it has to be either declared in that function, passed as a parameter to the function, or a global variable (or static data member of a class which is basically also a global variable). So these are the options:

//as a variable declared in the function:
void f() {
  int my_var = 42;
  cout << "my_var is: " << my_var << endl; //my_var is accessible in f() because it was declared in f().
};
int main() {
  f();
  return 0;
};

//as a passed parameter:
void f(int my_param) { //now my_param is a variable in f(), with the value my_var from main()
  cout << "my_param is: …
NichtSoGut commented: So much information, I've learnt loads because of it!! +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I would go one step further than gerard4143, I would say that it is not only O.K., but considered better practice in C++ to declare variables only where they are needed. In theory, it is faster. In practice it is just nicer because it keeps things localized in the code. If you have, for example, a large algorithm in one function and it requires many temporary or helper variables to do the various mathematical manipulations it needs. If you put all the variable declarations at the beginning, when someone reads you code, every time he encounters a new variable name he will have to visually scan through possibly the entire algorithm to see if that variable is meaningful in the algorithm or just a temporary. If it is declared on-site and within a reduced scope (like an "if" statement or inner-loop) then it is clear that it is a temporary or helper variable that is not relevant to the overall algorithm but just used to perform a local operation. Also, reduction of the scope of the variables can lead to better performance and will reduce the stack usage in a large function (i.e. if you have all variables at the start, the compiler has to generate an unecessarily large stack frame for that function, and every memory access operation will potentially be more costly if the stack is too large. While local declarations will make the stack frame be incrementally increased as the scopes of the function are encountered, and …

Aranarth commented: Indeed. +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Do you enjoy ruining peoples' lives like that?
The truth is better than false illusions.

>>If I knew EXACTLY how the whole process was done in every instance I'd do it,
Where does this logic end? Have you thought about that? You seem to be saying: I don't want to use an existing programming language because I don't know exactly what it translates to in machine code... I don't want to use existing machine code because I don't know how it translates to module executions on the CPU... I don't want to use existing CPUs because I don't know how it translates to moving charge in the integrated circuit... I don't want to use existing integrated circuits because I don't know how they move electrons around... I don't want to use existing semi-conductors because I don't know how it translates to quantum physics processes... I don't want to use existing quantum physics theory because I don't know how it translates to the fundamental laws of the Universe... come on... this thought process gets ridiculous very quickly.

>>Plus, lying and making me think I might do it is better than outright saying I won't.
No, it's not. Your parents might not want to burst your bubble and destroy your hopes. But you have to get real someday.

>>And last, do you know how the whole ENTIRE process of it is done, say, from absolute scratch?
In broad terms, yes, in details, no. A processor …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@Transcendant: If you are still having trouble with making this program work, I suggest you create a fresh new thread for it (because this thread seem to have about two posts related to the question out of 25 or so). I'm sorry (on "behalf" of daniweb) for the flame war that occurred on this thread. It is the first time I see this happen on this forum, and I hope it will not discourage you from posting questions again.

AndreRet commented: Cool +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

About pointers, there are two "alternatives" (the quote marks mean that they really can't completely replace pointers, but can significantly reduce the need for them).

First, a very popular design pattern in C++ is RAII (Resource Allocation Is Initialization). This just means that when an object is created it initializes the resources it needs and when it gets destroyed it frees them. I warn you, this relies on encapsulation. A simple example is the std::vector class in STL versus C-style dynamic arrays which use raw pointers. Consider those two equivalent codes:

int main() {
  std::vector<int> my_array;  //creating the object my_array also initializes it to a valid state.
  my_array.resize(50);        //requesting my_array to have a new size of 50
  for(int i=0;i<50;++i)       //looping around to set the values
    my_array[i] = i;
  return 0;
};                            //here, my_array gets out-of-scope -> destroyed -> frees the array of integers

int main() {
  int* my_array;           //creating a raw pointer with invalid state
  my_array = new int[50];  //allocating memory for 50 integers and storing its address in my_array
  for(int i=0;i<50;++i)    //looping around to set the values
    my_array[i] = i;
  delete[] my_array;       //deleting the array manually is required to avoid a memory leak.
  return 0;
};

You see, because std::vector is uses the RAII principle, the first piece of code is much superior to the second because there are no point where an invalid state exists and the user of std::vector doesn't have to worry about memory leaks (or more generally, the management of the resource, e.g. …

Narue commented: I feel sorry for you. Your well-intentioned and excellent post fell on deaf ears. +25
StuXYZ commented: Excellent post in a strange thread +4
thelamb commented: *copy/paste Narue's reputation* +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

As for the GCC downloads, if it is still relevant to you:

gcc-4.5.2.tar.bz2 -> this is the compiler(s) and standard libraries (this is the one to download)
gcc-ada-4.5.2.tar.gz -> this has the ADA compiler (most probably useless to you)
gcc-testsuite-4.5.2.tar.gz -> this is if you want to test that GCC works correctly (don't worry about that.. don't download)

Enjoy your coding! And come back to Daniweb if you are having trouble!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you have your own "home-brewed" project that you could make open-source, then what do you think is better on a résumé:

"I have worked on a little home project, and I think it's good."
OR
"I have started an open-source project, got several people on-board, managed to coordinate the work with them, and I even managed to get positive feedback from people who have used my code!"

I don't think that any employer would see the former as better than the latter. Of course, if you publish your code open-source, it also means that your potential employers will possibly take a look at it (I know I would). You run into the possibility that your code is not as good as you think and that might back-fire on you (it won't look good if you have an open-source project that includes no-one else and generally gets negative feedback).

Building a résumé is all about priorities. When you have little to show for, any little thing you have is good. Some years ago, I used to mention my home projects on the résumé or interview. Now, I have a lot more to put, so those are no longer included. I found that it is generally beneficial to at least show that you have some passion for what you do, and showing that you have spent a significant part of your free-time on home projects or an open-source one is a good way to show that. …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You need to compile both cpp files in the same compilation:

$ g++ HelloApp.cpp Hello.cpp -Wall -o HelloApp

Or, on an IDE (like VS or Code.Blocks), you would need to add all the .cpp files to the list of "source files" for the project (or solution).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

As far as I know, this expression:

(("%s",shared_memory) == "How are you my child?")

will always evaluate to false. The first part "("%s",shared_memory)" will first evaluate "%s", which does nothing, and then evaluate shared_memory, which does nothing, and then return the value of "shared_memory" which is a pointer. Then, the equal comparison will compare the pointer "shared_memory" with the pointer to the literal string "How are you my child?". That will always be false because all pointers have a unique value, unless they point to the same place.

You need to use either:

if(std::string(shared_memory) == "How are you my child?")

Or, as I have seen from your code, you seem to prefer C to C++, so I'm guessing you would want to use the old "deprecated" C version:

if( strcmp(shared_memory,"How are you my child?") == 0 )

That should fix it.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm not sure about the exact problem you have, but I think that reading this FAQ will shed some light on your issue. (You mind as well read that entire page, not just that one question)

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You have to understand that these expected errors are upper-bounds. I would think the messy curves you see (which is called "variance" btw) mostly have to do with the particular function used. For example, when the range includes a zero-crossing, then the way that the intervals (the small sub-divided intervals) of integration fall around the zero-crossing could have a big effect on the actual error. That would explain the "periodic" error curves you get.

I would suggest that you "sweep" the range of integration and take the maximum error. In other words, say that c = (b-a), then for a value of c (interval size), then pick M values of "a" within the period of the curve (maybe 0 to Pi or something.. maybe even picked at random) and perform the integration. Then, pick the maximum error obtained (from all the a values tried) for a given interval size c. This should get rid of this mess on the graph by eliminating the "chance" factor about where sub-intervals fall. And remember that the important quantity is not the actual curves you plot, but the line that hugs the upper-bound of your error the best.

As for round-off errors and floating-point precision, it might contribute to some small deviation from the expected results, but not that much.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, from the reference page on static_cast:

It can also cast pointers or references down and across the hierarchy as long as such conversion is available and unambiguous. No runtime checks are performed.

You see, static_cast is a compile-time casting operator. It will never do runtime checks (in fact it can't). I am guessing that proper compilers would warn you about such unsafe casts. But, it is allowed. Say, that for some reason, you have a pointer to a BaseClass, but you know that it must actually be pointing to an object of DerivedClass, then, using static_cast would be faster than the only alternative (i.e. dynamic_cast) and still "safe" (well.. as safe as you are sure of the "real" type of the object pointed to).

@deltamaster: >>you can use reinterpret_cast if you guarantee this operation to be safe, it is usually faster than static_cast.
You are wrong. reinterpret_cast is by far the least safe casting operator and it is not faster than static_cast. Also, in this case, it will not work at all because reinterpret_cast does not perform any shifting of the pointer's value. When you cast pointers to classes up or down the hierarchy, there can be an offset necessary on the "this" pointer, especially when multiple inheritance is involved. static_cast will blindly apply this offset at compile-time, while dynamic_cast will safely apply this offset at run-time (with a check). So, static_cast is not as safe as dynamic_cast, but it has no run-time overhead whatsoever …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your constructor for "testType" has no implementation. So the linker is looking for one and doesn't find it and thus throws: "unresolved external reference" (these words mean that your "reference" in the code, which is the call to the constructor, is assumed to be "external", i.e. found in another compiled library that is linked to your program, and the linker can't find it, i.e. "unresolved").

You need something like this:

template<class elemType>
class testType
{
public:
testType() {
  //something here.. or nothing, but you need the { } even if it is empty.
};
private:
int nothing;
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This may sound trivial, but I think that you need to be familiar with everything on this page. I mean, all the stuff on the left menu: IOStream library, String library, STL Containers, STL Algorithms and Miscellaneous. I don't mean to know all by heart of something like that. At least reading the synopsis (first page) of each of the STL containers and algorithms. This will allow you to reason about the choices for the containers and algorithms. Like saying: "I'm gonna use a std::list for this problem because the type to contain is large and expensive to copy, so it is worth the overhead of a double linked-list to gain the efficiency in insertion/deletion operations (which I anticipate to do a lot of)" or "I'm gonna use a std::map for this problem because I need fast O(logN) look-up operations and I don't have keys with the same value"... etc.

About the sorting, I think she was referring to some special linear-time sorting algorithms. If this is actually the answer that is "expected", then I guess I was wrong about the purpose of the question. This is a very theoretical answer since these algorithms are seldom used in practice (because they lack generality, so people use them only in very special circumstances). Sure, in that question, it seems the bucket-style sort would be the best, but only because it is a hypothetical situation where the numbers to be sorted are actually random and uniformly distributed …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

1) This line:

class OSG_EXPORT Group : public Node

means that the class Group can be exported. This if because when you compile this code into a shared library (.so or .dll), you can export the entire class. This is rarely used in practice because there are binary compatibility problems with doing that. So, the "OSG_EXPORT" is simply a #define that is probably defined like this (not exactly, you can find it for yourself in their source code):

#ifdef OSG_COMPILING_SHARED_LIBRARY
#define OSG_EXPORT __declspec(dllexport)
#else
#define OSG_EXPORT __declspec(dllimport)
#endif

The above just means that the class' implementation will be exported from the dll it is compiled to, or imported from the dll it was compiled in (if you are using this code outside the source code of OSG).

2) This line:

Group(const Group&,const CopyOp& copyop=CopyOp::SHALLOW_COPY);

just means that if you use the copy-constructor in the default way (i.e. Group g1(g2)), then, the copy will be a shallow copy (meaning the pointers or handles inside the Group object will be copied, but the memory or resources they refer to will not be duplicated; basically, both copies will share a pointer or handle to the same memory or resource). But this function also allows for an optional parameter to make it a deep-copy (probably used like so: Group g1(g2, CopyOp::DEEP_COPY)). The deep-copy refers to the opposite of the shallow-copy, that is, all the resources and memory are duplicated for the new copy of the object.

Personally, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This should help you understand what is going on (compile, run and play with this):

int main(int argc, char *argv[]) {

  cout << "the 0th argument is: " << argv[0] << endl;
  cout << "it first two chars are: " << argv[0][0] << " " << argv[0][1] << endl;

  cout << "all the other arguments were:" << endl;
  for(int i = 1; i < argc; ++i) 
    cout << argv[i] << endl;
  
  return 0;
};

argc is the number of arguments in the command-line (which includes the application's name).

argv is an array of C-strings (char*), the size of the array is argc. Each element in the array "argv" is a C-string. The zeroth being the name of the application itself, and the rest being each command-line argument (separated by spaces) (note that arguments between quotes "" will be put into one such C-string).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You are asking which language you should program in.. on a C++ forum! I think you know where this is going to lead.

C++ plays the central role in the world of computer programming. What that means is that all other languages define themselves in comparison to C++. It means most languages try to have a C++-like syntax to have the best chance of appealing to the massive body of C++ programmers, which means most other languages are easiest to learn when coming from a C++ background. It means also that most (if not all) platforms, operating systems, software tools, etc. are either natively in C++ or provide direct (or very good) compatibility/interface with it. Finally, it means that C++ is key in having broad competences in programming.

The above are (sort-of) facts, that might not mean that C++ is the best to start with. In my opinion, it is. But I'm a bit tough. People say that C++ has a steep learning curve (at least at first), and I would also say it's very long, but mostly because C++ is not limited to OOP, it has two more levels, i.e. generic programming and template meta-programming (that other languages don't have, or only partially).

The criticism you most often hear of C++ is that it is too close to hardware (too low-level), too complicated to port between platforms, and that memory management (or the lack thereof) in C++ is too error-prone. Yet, most companies that use C++ …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Another problem you will have is that each compilation of those separate cpp files will have its own instances of "playerClass" and "warrior". This most probably not desirable. You could fix this with use of the "extern" keyword in front of those two global variable declaration, but I cannot, for the life of me, recommend that.

I highly suggest you make all your game functions as part of a game class (that handles the game):
gamefunctions.h:

#include "PlayerClass.h"
//using namespace std; //do not import namespaces in a header file!!


class Game {
  private:
    //PlayerList
    //Class,Health,Mana,Gold,Armor,BaseAttack,RangeOfAttack
    Player warrior;
    Player playerClass;

  public:
    Game() : warrior("Warrior",150,10,0,1,20,5), playerClass("",0,0,0,0,0,0) { }; 
  
    void hPlayer(int);
    //all your other functions ...
};

Then in gamefunctions.cpp (or in a few separate cpp files):

#include <iostream>
#include <iomanip>
#include "gamefunctions.h"

void Game::hPlayer(int PlayerC) // now a member function.
{ 
    //And the rest of the code remains essentially unchanged.
    switch (PlayerC) 
    {
        case 1:
            playerClass.setHitPoints(warrior.getHitPoints());
            break;
    }
}

And finally in main.cpp:

#include <cmath>
#include "gamefunctions.h"
using namespace std;

int main()
{
    srand(time(0));
    Game my_game;    //create an instance of the game!
    my_game.intro(); //and run it!
}

That ought to be much better than relying on global data. BTW, you can very often replace global data with an enclosing "super" class. With this, you will be one step closer to breaking the C-programming habits and becoming a C++ programmer!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I can't give you much book suggestions or basic online tutorial (because my years of learning basic C++ are far behind me), but there is one site (in addition to www.cplusplus.com) that is key resource for understanding and knowing how to program well, that is: http://www.parashift.com/c++-faq-lite/

As for learning C before getting into C++: C is more low-level and require you to deal with memory allocation, arrays, pointers, null-terminated strings, etc., and these low-level processes occur "under-the-hood" of C++ standard library functions and classes. I would say that it is important to understand C code and how it is done such that you have a good idea of what is happening under-the-hood of C++ code. But, don't "learn C" in the sense of becoming proficient at it. Because if you are too accustomed to C programming you run into the danger of moving into C++ programming and wanting to resort to those C functions and constructs that you are familiar with and these are almost always a worse and less-effective choice than their C++ equivalents.

One caveat on that, if you are already familiar with another programming language similar to C (like Fortran, Matlab, Pascal, etc.) and you are comfortable with how procedural programming works (you know concepts like variables, types, identifiers, pointers, parameters, functions, dynamic arrays, stack vs. heap, compile-time vs. run-time, etc.) then you can go straight to C++. So, basically, understanding C before learning C++, is another way of saying, understand …

kvprajapati commented: Well said! +12
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There are a few inefficiencies about your implementation (the push_back() is only one of them). Basically, you should avoid allocating memory within a loop. This is why push_back is inefficient because it re-allocates and copies the memory at each iteration (although STL containers like vector are amortized, but still..). Also, the new allocation of this tempItem at every outer iteration is also very inefficient. I propose something like this:

//First, figure out what the maximum size for tempItem should be:
int maxSize = 1;
for(int q = 0; q < tableCount; q++)
  for(int j = 0; j < inTables[q].Items.size(); j++)
    if(maxSize < inTables[q].Items[j].Size)
      maxSize = inTable[q].Items[j].Size; //notice that using [j] is more efficient than .at(j) (skips useless bound-checking)
//Then, allocate enough memory for tempItem, and do it only once.
char *tempItem = new char[maxSize]; 
for (int q = 0; q < tableCount; q++) //using native int type is more efficient than a special type like "unsigned long int".
{
  for (int j = 0; j < inTables[q].Items.size(); j++)
  {
    //Read the data, and tempItem is guaranteed to be big enough to store the data.
    inFileDrs.read(tempItem, inTables[q].Items[j].Size);
    //Allocate enough space for the data in your vector:
    inTables[q].Items[j].Data.resize(inTables[q].Items[j].Size);
    //Then, just copy, using std::copy (from #include <algorithm>) (or you could use a loop too)
    std::copy(tempItem,tempItem + inTables[q].Items[j].Size, inTables[q].Items[j].Data.begin());
  }
}
delete[] tempItem;

However, I'm pretty sure that the following will work just fine (maybe you should verify that it does):

for (int q = 0; q < tableCount; q++) {
  for …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Maybe I am getting confused between read and write...

Read-> take and store into the stream.
Write-> write out from the stream to the vector.

You are confused about the process. The stream does not store memory. Only the vector<char> store the memory. So, what you do is you start with an input vector<char>, link it to a stringstream object, then, using the stream you can access the memory directly to read-off all those values you need to alter. Then you figure out how large the output vector needs to be. Create an output vector<char> that is of the right size (using resize or through the constructor). Then you link this vector to another stringstream object, which you use to write all those values into the output vector. Finally, you return the output vector as a result of the function.

The C# code that you posted does this in a slightly different (and quite stupid) way. But, hey, what do you expect from a C# programmer anyways?

Anyhow, since this is dragging on, I just translated the C# code you posted, except for the parts between /****/ lines and a few things at the end. I hope that you can figure out the rest, because I cannot make it any clearer at this point (I've run out of things to explain).

#include <iostream>
#include <sstream>
#include "stdint.h"

vector<char> Decode(vector<char>& data) {

    stringstream reader;
    reader.rdbuf()->pubsetbuf(&data[0],data.size()); // create variable        

    // testing patch version
    uint32 version; reader.read(reinterpret_cast<char*>(&version),sizeof(version));
    if (version …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Sure you can specify the type in advance using the <>. That is called "explicit instantiation" of the template. But, as I said before, you need to use a function pointer type, this means that you must take the address (using &) of the function before you pass it to the function template. For instance, you could do this:

template<typename t>
void trimr(std::basic_string<t>& s){
    if (typeid(basic_string<char>())==typeid(s))
        trimr<char,bool(*)(char)>(s,&iz_space);
    else
        trimr<wchar_t,bool(*)(wchar_t)>(s,&iz_wspace);
}

But I don't think that the explicit specification of the template arguments is what makes the above work. What makes it work is the & before the function, to make them function pointers.

BTW, have you considered using template specialization to improve your implementation. Here is what you could do:

template<typename t>
void trimr(std::basic_string<t>& s); //leave this intentionally not implemented.

//specialize it for char and wchar_t:
template <>
void trimr(std::basic_string<char>& s) {
  trimr(s,&iz_space);
}

template <>
void trimr(std::basic_string<wchar_t>& s) {
  trimr(s,&iz_wspace);
}

This way, if someone tries to call trimr with anything other than "char" or "wchar_t", it will throw a compile-time error like (for float instead of char) "unresolved reference to trimr with [t = float]".

But, to do it even better, I would suggest using type traits, as so:

#include <cstdlib>
#include <iostream>
#include <cctype>
#include <string>
#include <cwctype>
#include <typeinfo>

using namespace std;

template <typename T>
struct my_char_trait { }; //intentionally left blank.

//specialize for both char types:
template <>
struct my_char_trait<char> {
  static bool is_space(char ch) { return isspace(ch); };
}; …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

different return types be supported by one function so you can use int, float, double, etc vs making several of the same function with different return types.

Your definition of the use of templates is completely wrong (or at least extremely reductionist). First of all, what you are describing is "function overloading" (you can use function templates to have the same effect but it is usually worse than overloading, certainly not in the code you posted). And having different return types for the functions is not possible in neither function overloading nor function templates. The C++ compiler cannot resolve which function to use based only on the return type. This is why you cannot have function overloads or function templates that only differ by the return type. This is exactly the error that your compiler is giving you for the function showWeaponSpecs() because it does not have a parameter whose type depends on the template argument. You can fix it by either not using function templates for the above code and use a void return type (highly recommended!), or by using a dummy parameter, or by instantiating the function call explicitly "M16A4.showWeaponSpecs<int>();".

I suggest to read up seriously on templates because they are so much more powerful than what you are using them for (in fact, what you are using them for is a travesty! IMO). And as firstPerson already pointed out, if you call the function with the wrong type, you will get a compile-time error inside your …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It would be: (don't use firstPerson's code, its faulty.. sorry fP..)

int main(){
  unsigned char c1 = 0x56;
  unsigned char c2 = 0x78;
  unsigned char c3 = 0x92;
  unsigned char c4 = 0xF0;
  int combined = ((c1 << 24)| (c2 << 16) | (c3 << 8) | (c4 << 0)); //construct 32bit unsigned integer from 4 unsigned chars (i.e. bytes).
  cout << "Combined = " << showbase << hex << combined << endl;
  
  //now, to reconstruct the four bytes:
  unsigned int byte1 = (combined >> 24) & 0xFF;
  unsigned int byte2 = (combined >> 16) & 0xFF;
  unsigned int byte3 = (combined >> 8) & 0xFF;
  unsigned int byte4 = combined & 0xFF;
  cout << "Byte1 = " << showbase << hex << byte1 
       << "Byte2 = " << showbase << hex << byte2
       << "Byte3 = " << showbase << hex << byte3
       << "Byte4 = " << showbase << hex << byte4 << endl;
}

If you want to store a vector of bytes in a way that is closest to the type byte, you should store them as "unsigned char" not "char", you run in the danger of chars being interpreted as either ASCII characters or as signed integers (either one is not what you want, from looking at the C# code).

However, I must mention. Using a vector of chars (or unsigned chars) is far from being the easiest thing to do in this case. I would suggest that you look at

MasterGberry commented: Very thorough explanation :) +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you see a class template declared as so:

template <class SomeType>
class Foo {
  //...
};

It means that to use this class, you need to provide another class (or type in general) as argument to the template. The STL queue type is similar (except that it has a few more template arguments that have default values). This means you need to put some sort of type name as template argument, as in the following, for a queue of integers:

std::queue<int> myQueue;

From the looks of your code, it seems that really what you want to have is just like in the above, that is, a queue of integers. So, your class should be declared as:

//#include <iostream>
//#include <fstream> //don't include unnecessary headers (include them in the cpp instead.
#include <queue>
//using namespace std; //don't import namespaces in a header file.

//template <int T> //T seems to be useless and BruteForce does not need to be a class template.
class BruteForce {
  private:
    int currentItem, nextItem;
    std::queue<int> q;
  public:
    void MakeQueue();
    void GetPercepts();
    int reflexAgent (int,int);
    void DisplayInfo();	
};

The reason you had the error that you had is because you declared BruteForce as a class template with an integer-valued argument. Because template arguments can be either a type name (or a variation of that) or a constant value (known at compile-time) of some primitive type (int, float, double, char, etc... but not pointers or string types). This is actually an extremely powerful feature, but …

rcmango commented: Thankyou! Your feedback helped me a great deal. +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Dev-C++ is outdated. The version of GCC that comes with it is 3.4! The current version of gcc is 4.4.5. We have also encountered several people posting threads on this forum about problems related to DevC++, including compatibility issues with the newer versions of Windows (Vista and 7). So I wouldn't recommend it for those reasons, regardless of the nice features it may have.

CodeBlocks or VS (Express) would be the way to go if you want an IDE. Certainly for the compiler alone, GCC is the best (that is free.. if you have an endless money supply, you could get the intel compiler (ICC) which is the only one that is better than GCC).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Did you initialize the list "Seats". If it is empty, then that would explain your error. Make sure it is not empty.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It looks like you have a fixed number of elements in the table and they are simple bool type. I would suggest you use either a static array or a class vector instead of list. The error you are reporting is weird... normally, this should execute just fine. The error is either in the definition of Table (and GetSeats()) or that you have some non-standard (and faulty) implementation of the C++ STL. Please provide details on the definition of Table and what platform this is running on. Maybe you could try using "vector" instead of "list", just for a quick-fix of the problem.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm assuming that you know that when you click on "run" in VS, all it does is compile your project into a .exe, that you can find somewhere in your project folder, and then executes it. Finding that exe and double-clicking on it will run it "outside" VS. But that's not the end of it.
If you want to _distribute_ your application, there are two things (that I can think of) that you need to worry about:
1) Compile your application in RELEASE mode (not in the default DEBUG mode that it usually gets compiled in). This will purge out any debug symbols and other things that generally facilitates debugging but is generally a bit slower to run.
2) Follow these guidelines. This will tell you what you need to distribute or install along-side your application if it is to be run on another computer that doesn't have VS. Usually, you try to limit those external dependencies as much as possible.

Beyond that, I guess you might want to take your program and run it on a few other computers (from friends, colleagues, or school terminals) to see if there are any compatibility issues (try to find computers with minimal other installations and different versions of Windows).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Just for fun, I cooked up a little algorithm of my own, without going as far as getting into bit operation-style algorithms. So, in a few minutes or so I got this algorithm which I think is fairly elegant and short:

void genPrimeNumbers(int n) {
  vector< pair<int,int> > accum;
  accum.reserve(n);
  accum.push_back(pair<int,int>(2,4)); 
  cout << endl << setw(20) << 2; cout.flush();
  
  for(int i = 3; accum.size() < n; ++i) {
    bool is_prime = true;
    for(vector< pair<int,int> >::iterator it = accum.begin(); it != accum.end(); ++it) {
      while( it->second < i )
        it->second += it->first;
      if( it->second == i ) {
        is_prime = false;
        break;
      };
    };
    if(is_prime) {
      cout << "\r" << setw(20) << i; cout.flush();
      accum.push_back(pair<int,int>(i,i+i));
    };
  };
};

It just prints out the values and I have checked that it works.
The performance is reasonable given the low level of sophistication of the algorithm:
gets the first 100,000 primes in 5.37 seconds
gets the first 1,000,000 primes in 545 seconds
That is on a 2.8 GHz processor (the program is single-threaded so it uses only one of my 8 processors) with 8M of L3 cache... and the rest of the specs is not so relevant.

EDIT: For the record, the performance is about 20 times worse with the -O0 flag instead of the -O3 flag (-O4 or -O5 made no further improvement).

Clinton Portis commented: fast algorithm. few lines of code. +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Read this.

In the link you will find a good enough explanation why it is not good to throw pointers. My take on it is: What if the dynamic allocation fails and throws an exception of its own? Basically, in that case, you will never reach the actual throw statement, you might not catch the exception and then you will never know where your program actually failed. Throwing by value (temporary) and catching by reference is the way to go.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The errors you have posted are due to old (very old.. from the days when 16bit computers where common-place) C code that uses these "far" and "huge" keywords for the pointer type "DIBPTR". These keywords are completely obsolete nowadays. I guess they are not supported by C++ compilers (one of the few special features of C that has not been kept backward-compatible in C++). So make sure that all the code that uses this sip.h gets compiled by a C compiler (gcc) and usually all files ending with .c should also be compiled by a C compiler (although the guy who wrote the code may have been sloppy with this as people sometimes write C++ code in .c files because they are stupid). I'm not in any way familiar with CodeBlocks build system so I cannot tell you how to make this work (if you are really hoping to compile this cross-platform, I might suggest you use cmake for the build system).

For a quick-fix of your error above, you could just remove the far and huge keywords and it should work. However, this error might just be the tip of the iceberg. Compiling very old C code in a C++ compiler or interfacing it to C++ code is usually difficult and sometimes it might be easier to just re-implement it in C++ (or at least C-style code that is usable with a C++ project).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This is a huge design issue. I will try my best to keep it brief. I will go from worse to best options, in my humble opinion (from experience in making a few simple computer games and having incrementally implemented a better solution each time).

Global variables are horrible.. even POD-types. Try to avoid them at all costs. They are a very very last resort. Philosophically, the motivation is that in OOP, you want objects to encapsulate the state of the application. This way you implement each class such that they maintain a valid and working state (except in error-states, where they should be duly reported or logged). If you have global variables, your application has a state that is independent of its objects and it becomes a nightmare to keep it stable because now all classes have to be implemented to preserve some ill-defined application state. Now, global _constants_ are much different. If you need a bunch of values like some physical constants (e.g. gravity or Plank's constant) or mathematical constants (e.g. Pi or e), they don't define the state of the application since they don't change, so you can safely use global constants to store those values (but make sure they are POD though). To avoid name-clashing, split them up into their most suited namespaces.

Singletons are not nice and should be avoided. But for some purposes, they are really the only solution. As for the implementation, there have been a few prior posts with suggestions, …

jonsca commented: Excellent +6
kerp commented: Great post +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your question is too vague and I think arkoenig and firstPerson's answers are quite good instructions for the "generic" small-code performance testing and optimization.

Overall, people usually talk about three levels of optimization: macro-, micro-, and nano-optimization. You want to proceed through them in that order. Macro-optimization is about defining the software architecture that properly splits memory and processing, this is done before you program a single line of code! This is like the first and second step that arkoenig posted. It is by far the most important because it is the hardest to fix and the hardest to measure. You have to really make sure you understand the problem you are trying to solve and that you are able to divide the problem into subproblems that are as independent from each other as possible. When your input/outputs are well attributed and thought-out for each subproblem, and that you managed to get a good, clean separation of memory between the subproblems (memory locality is a big factor in running speed), then the software architecture (what classes or functions you will make and in which libraries they will be put) follows quite naturally. If you screw up at this stage, you are in trouble, because down the line, if you find it to be inefficient, you might have to start the whole thing from scratch.

The second step is micro-optimization. Once you have coded all your functions and classes in the most straight-forward way that works correctly, then you …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There are several options for this problem (which is quite usual in numerical simulation code.. where to put the simulation parameters?). I could suggest two that seem to stick out for me:

1) Make a POD-style class (e.g. C-struct) that has all the parameters:

struct SimulationSettings {
  a, b, c;
};

Then have the class A take a const reference to a SimulationSettings structure and hold this reference as a data member. This way, you can associate all the instances of A to a single set of SimulationSettings. To speed things up a bit, try to reduce the use of the simulation parameters or make a more local copy of it (increase memory usage to reduce time taken at dereferencing). In my own experience, I don't think you will have to worry about this too much at the computational level (do the profiling, as suggested). The nice feature of this solution is that you are not directly tying the implementation of class A to the implementation of class SIMULATION (as you would if you had a pointer or reference to SIMULATION in the class A).

2) It might not be appropriate for all settings and stuff, but have you considered using template parameters? For example:

template <double a, double b, double c>
class A {
  A();
};

template <double a, double b, double c>
class SIMULATION {
  vector< A<a,b,c> > array;
};

This way, you have ZERO run-time overhead (memory or time). The drawback is that …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Please don't do what AD suggested (sorry AD..)! That is dangerous, unstable, and bad style. Unless the classes are all POD classes without virtual methods, this saving method will crash when you try to load the file again.

What you are trying to do is called serialization. There are several ways to do it, from the crudest to the most sophisticated. One, most sophisticated method, would be that of the Boost.Serialization library. While the crudest method (that also requires the least amount of C++ skill) is to simply have a save and load method in each of your classes:

#include <fstream>
using std::ofstream;
using std::ifstream;

class A
{
   // blabla
  public:
    void save(ofstream& outfile) const {
      outfile.write(&data_member1,sizeof(data_member1));
      //.. and so on for all data members.
    };
    void load(ifstream& infile) {
      infile.read(&data_member1,sizeof(data_member1));
      //.. and so on for all data members (same order as in the save method).
    };
};

class B
{
   // blabla
  public:
    //.. save & load, as for A
};

class C
{
   // blabla
  public:
    //.. save & load, as for A
};

int main()
{
   A a;
   B b;
   C c;

   // now save the data
    ofstream file_ptr; // Declares a file pointer.
    file_ptr.open(“house.dat”, ios::out); // Creates the file.
    if (!file_ptr)
    { cout << “Error opening file.\n”; }
    else
    {
    // Rest of output commands go here.
       a.save(file_ptr);
       b.save(file_ptr);
       c.save(file_ptr);
          
    }
}

In the above implementation, if you have any data members which are of a class, then you would call its …

jonsca commented: Nice post. +6
gerard4143 commented: Very interesting point Mike..Oops forgot about the vtables and vdestuctors +4
Ancient Dragon commented: Correct +34
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here is how it should work:

void expand() {
        int oldlen = actual_len;
        actual_len += increment;
        DynamicType* temp = new DynamicType[actual_len];
        DynamicType* temp_begin = temp;
        data = data_begin;
        for (int i = 0; i < oldlen; i++) {
            temp->what_type = data->what_type;
            if (temp->what_type == temp->is_int)
                temp->integer = data->integer;
            else if (temp->what_type == temp->is_string)
                temp->string = data->string;
            temp++;
            data++;
        }
        delete[] data_begin; //notice this line has changed
        data = temp;
        data_end = temp;
        data_begin = temp_begin;
    }

Since you are allocating an array, you should use the delete[] operator (not just "delete"). Also, since you have been incrementing data up to the end of the "oldlen", you need to delete the original pointer, i.e. "data_begin".

Note: typically, these dynamic arrays are implemented by doubling the capacity every time you need an expansion (not using a fixed increment). Algorithmically, it makes no sense to use a fixed increment for the capacity because it's not scalable. If your program ends up needing 18 elements in the array, you will require 2 memory re-allocations and copy (instead of 18 if you keep only the exact number of elements needed). However, if your program needs one million elements, then you will require 100,000 reallocations (that is only a 90% improvement). If you grow the array size by a factor of 2 each time you need more space, you end-up needing at most 20 reallocations, that's much better!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Hey David! I know you solved it, but if you want a more generic solution, I can suggest something. This case is a very good example of when traits can be very useful.

Consider this:

//define a type trait for images:
template <class T>
struct image_trait {
  typedef typename T::Pointer Pointer;
  struct PixelType {
    typedef typename T::PixelType::Type Type;
    static T::PixelType::Type Zero() { return T::PixelType::Zero(); };
  };
};

//specialize the trait for a primitive image (like unsigned char*)
template <>
struct image_trait<unsigned char*> {
  typedef unsigned char** Pointer;
  struct PixelType {
    typedef char Type;
    static char Zero() { return 0; };
  };
};

//then, you can have one function template that will work for all image types that have an appropriate image_trait (either the generic one or a specialization)
template <class T>
void CreateBlankPatch(typename image_trait<T>::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch(patch, typename image_trait<T>::PixelType::Zero(), sideLength);
}

This is how STL implements a lot of things. Like for iterators, all the STL algorithms can also work for pointer instead because, internally, they always go through a iterator_trait template to know the value type, reference type, etc., and a few specialization for pointers (like T*) make the STL algorithms compatible with them (or any other custom iterator you could come up with, as long as you provide a valid iterator_trait for it).

StuXYZ commented: Short simple post on Traits: Thx +4
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Isn't glBegin depracted?
You're right. I have to admit that my knowledge of OpenGL dates back a few years (version 2.0 was the latest I had worked with). I had just assumed that you meant deprecated as in being undesirable. glBegin/glEnd style commands have always been "ugly" and slow, and rarely useful because VBO (or just "vertex buffers" as they used to be called) are much more generic and once you use them, there is no point for glBegin/glEnd structures anymore. So, you're right, you shouldn't use the second example I posted, because it appears that display lists are also deprecated (and nothing equivalent exists anymore, which is a shame because they were nice and very fast if the hardware supported it well).

>>So the memory leak might be a natural growth of the heap?
>> ... going 4 K per second and after a while it stops. Is this supposed to happen?
Ok, so, the "heap" is the entity from the OS that dynamically allocates memory (new/delete, malloc/free). To do that, it manages a chunk(s) of RAM that the OS gives to the heap dedicated to your application. The more you request memory from the heap, the more the heap has to request from the OS. But when you free memory (as you should), you create "holes" at random places inside the heap's memory. In subsequent allocations of memory, the heap will try and reuse those holes, but if it doesn't find a hole that …

DaSpirit commented: Really helpful, nice guy. +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I don't know about the memory leak (I would assume it is just a natural growth of the heap.. wouldn't worry about it too much).

What you are rendering is so trivial that you probably don't need VBOs (they are more critical when rendering meshes, e.g., a large complex model). Here is how to do it anyways:

GLuint vbo_ids[2];
  glGenBuffers(2,vbo_ids); //generate two buffers.
  
  //create arrays that store the points and colors for first geometry:
  GLfloat points1[] = {400.0, 160.0, 320.0, 440.0, 480.0, 440.0};

  glBindBuffer(GL_ARRAY_BUFFER, vbo_ids[0]);
  glBufferData(GL_ARRAY_BUFFER, 6*sizeof(GLfloat), points1, GL_STATIC_DRAW);
  
  //repeat for second geometry... you can also intertwine the data:
  GLfloat buf2[] = { 0, 0,  //tex-coord 1
                     100.0, 100.0, 0.0, //vertex 1
                     0.5, 0, //tex-coord 2
                     228.0, 100.0, 0.0, //vertex 2
                     0.5, 1, //tex-coord 3
                     228.0, 228.0, 0.0, //vertex 3
                     0, 1, //tex-coord 4
                     100.0, 228.0, 0.0 }; //vertex 4

  glBindBuffer(GL_ARRAY_BUFFER, vbo_ids[1]);
  glBufferData(GL_ARRAY_BUFFER, 20*sizeof(GLfloat), buf2, GL_STATIC_DRAW);

  while (!done)
  {
    SDL_Event event;
    while (SDL_PollEvent(&event))
    { //.. let's skip this stuff.. just to make it cleaner for the example...
    }

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0f,1.0f,1.0f);

    glBindBuffer(GL_ARRAY_BUFFER,vbo_ids[0]);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableClientState(GL_VERTEX_ARRAY);

    glEnable( GL_TEXTURE_2D );
    // Bind the texture to which subsequent calls refer to
    glBindTexture( GL_TEXTURE_2D, ret );
 
    glEnable (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glColor3f(1.0f,1.0f,1.0f);

    glBindBuffer(GL_ARRAY_BUFFER, vbo_ids[1]);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, 5*sizeof(GLfloat), 2*sizeof(GLfloat));
    glTexCoordPointer(2, GL_FLOAT, 5*sizeof(GLfloat), 0);

    glDrawArrays( GL_QUADS, 0, 4);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDisable( GL_TEXTURE_2D );
    glDisable (GL_BLEND); 
    glClearColor(0.7f, 0.9f, 1.0f, 1.0f); //remark: this only needs to be set once.

    SDL_GL_SwapBuffers();
    SDL_Delay(1000/30);		
  }

But, actually, for your application, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Wait a minute... what learning algorithm are you actually implementing? Your code looks like nothing I can recognize. Are you trying to implement this formula:

T_{ij}^{\rm new} = T_{ij}^{\rm old} + M_i^{\rm new}M_j^{\rm new}

This formula is a simple sum. You need to first initialize all weights to zero. Then you have three nested loops (M is the number of patterns and N is the number of neurons):

for each pattern m of M
  for each neuron i of N
    for each weight j of N
       w[i*N+j] += p[m*N+j]*p[m*N+i];

And that's it.. hence my earlier comment about this implementation being trivial.

If it is another algorithm you are implementing, please post the details or at least a link to a page describing it.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Guarding the header is enough, it guarantees that the header's definitions only appear once. So having a guard inside a guard is useless (not incorrect per se, but useless).

You have to soften your coding standards. Most rules are not that strict, as Sutter and Alexandrescu already point out in their introduction. You are taking a basic guideline of trying to avoid using #defines (because they are harder to maintain and can cause name clashes) to an extreme. You see, the C++ standard committee bends this rule for certain trivial stuff like "NULL" or "TRUE/FALSE", that should tell you that it is totally fine for these universal constants that cannot be mistaken for something else and will never change.

The most blatant coding standard that you are violating here is the fact that you are including headers that are not useful because you assume that any other library that uses your header will also use windows. That breaks rule 23 of the book and is also against the philosophy of rule 59. If you have a bundle of header files that very often all need to get included in many of your other h or cpp files, you can always make a separate header file like "headers_for_this_purpose.h" where you include the bundle of headers (and guard this header too, of course).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you pay attention to this sentence:
>>These last four classes are all expanded to have a graphical implementation with SDL.
You see that the last four classes should be expanded to include some display function (and maybe others). This calls for multiple inheritance. You can make another base class which is dependent on SDL and has this pure virtual "display" function with whatever parameters you need. Now, your last four classes should inherit from their respective base class AND from this SDL visible object class.

This way, all the code that uses the other base classes (Entity, PlayerEntity, etc.) doesn't need to have any dependence on SDL. And your code that handles the rendering and the SDL window can simply keep a record of all SDL visible objects (as base classes) and call their virtual methods for displaying them.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It seems alright to me as far as the procedure you have taken to export the class from the DLL. That is the way to do it, as far as I know, but I don't do it often because of the remarks that follow.

One important thing that always needs to be mentioned when talking about exporting C++ classes from DLLs is that you have to make sure that all the code that uses this DLL is also compiled with the exact same compiler (same version (major, minor and revision), same OS, same platform (32bit or 64bit)). So, that is very restrictive and often makes the whole idea of using DLL to export classes very impractical. This link provides you a simple explanation of the problem. Basically, the options to cope with this problems are to either:
- export only C functions from DLLs (no class methods nor objects as parameters).
- use a ready-made ABI like COM, ActiveX, or whatever (this will basically confine you to Windows, I don't know of any major ABI that is cross-platform).
- follow very strict rules in your programming style to ensure binary compatibility (which is not a trivial task, relies heavily on the PImpl idiom (Cheshire Cat or Compiler Firewall)).
- stick to one single compiler and OS, and recompile your DLLs for every distribution or new minor version of all compilers (very hard to maintain if you expect wide distribution over some period of …

claudiordgz commented: Again... priceless help :D +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

For the record, I'm not an expert on Hopfield nets (but have dealt with other types of ANN).

You are right, you only need one matrix of weights if you have less than the maximum number of patterns for a given net. The Hebbian rule is quite trivial to implement if you look at this link.

Remember also that basically, you need the patterns to be reasonably "uncorrelated" in order to represent them uniquely with the net. This means that generating them at random might not be the greatest idea. Maybe you should test a pattern to see if it is not correlated too much with the other patterns before you add it to the set (if the Hamming distance between two patterns is to low, you might want to generate a new one). Another way to look at this is through the entropy of the set of patterns (with base 2, the entropy is equal to the number of truly distinct patterns in the set).