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

Epic: Surpassing the usual or ordinary, particularly in scope or size.
Rant: To utter or express with violence or extravagance.
I think those terms apply very well to Torvalds' forum post (it's made epic because of the "celebrity" status of Linus Torvalds).

Rebuttal: The act of refuting by offering a contrary contention or argument.
I think this term applies very well to the article I linked to.

Where's the contradiction?

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

>>He mentioned on a number of occasions that Torvald only cited one example for his argument
He mentions that problem in Torvalds' rant one time in the whole rebuttal.

>>only cited one example himself for his.
Actually, if you just do a word-find for "example", you will easily spot 4-5 examples given of where C "promotes" bad-style or at least does not hold up against C++'s features.
Anyways, the claims are very different. Claiming that something is true requires evidence (more than one example). Refuting the claim by saying that there is no evidence to support it, does not require evidence (and giving counter-examples is just a bonus). The main theme of the rebuttal article is that all the strong claims that Torvalds made in his epic rant are not supported by evidence (or, at least, far from enough evidence). I mean, this is just a basic exercise of critical thinking (dissecting an argument for what it is worth). The author of the rebuttal might go over the boundary of an objective treatise here and there, but the main conclusion is what is important: "Claiming that C somehow encourages people to make better, cleaner and more efficient code is simply false." (note: _claiming_ C is better is false, claiming the opposite (that C++ is better) would require a lot of evidence and the author is very careful not to make that claim). I linked it mainly because I found his description of the "C-hacker syndrome" very …

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

>>that link, but kudos on a huge rant.
The article I linked to was not a rant, it was an epic, logical rebuttal of Linus Torvalds' crazy rant against C++ (which is also worth reading just for how ridiculous it sounds). But that does not in any way diminish Torvalds' awesome programming talent, but just shows that he is human (with all that it entails).

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

@rubberman, I certainly meant no disrespect and I have no problem with mixed C/C++ programming (especially when done by professionals). I just like to point out to those who are learning (the OP) the pure C++ techniques and functions because I think that in the long run it's better to get used to STL style programming as early as possible, but that's just my (not so) humble opinion. On a final note, I hope, for your sake, that you are not suffering from the C-hacker syndrome, you know that the first step to recovery is admission (a few red flags from your post: "C-style functional programming is just cleaner", "a lot (I think) easier to use", "using what makes the most sense to me", etc. these are not rational nor objective arguments, no offense, but they do sound an awful lot like they come from a C-hacker).

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

@WaltP

>>Disagree -- based on the definition of the problem. User does not mean the person running the program. User means the programmer, and it is a very appropriate way to teach techniques.

Of course the user is not the person running the program, I never assumed it was. My assumption was that the user is the programmer which is using the class (or code in general) that you have written. And in this case, it is very reasonable to say that delegating responsibilities to the user is bad design. You say it is an "appropriate way to teach techniques"... ?!?!? Even if it was the case (and it is not), it would be a ridiculous thing to say. You don't write code such that you can teach the user about programming techniques! When you write library code, it's to be useful to whoever wants to use it. It's more productive and effective to write code that puts the least amount of responsibility on the user, simply because it reduces the amount of errors that the user could commit if he doesn't completely understand your library or is not aware of the implementation details. That's the whole point of encapsulation. You must assume that if it is possible for the user to mishandle your library, then a user might eventually do so, and thus, you need to make that either impossible or very difficult to do.

>>throwing an exception by definition is a failure.

Dude, you …

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

First of all, the code that you posted has several errors. First, the array "b" is not a dynamically allocated array, it is a fixed-size array (deduced from the number of elements between curly braces) that resides on the stack frame of the function. This means that after you return from the function, that array will no longer exist and the pointer that you have provided to the caller will be invalid. Second, the memory that is allocated by "a = new int;" is only big enough for 1 integer value. Third, when you do "a=b;" you are just making the pointer a to point to the same location as b, which is the start of the static array that will disappear when you return from the function. Finally, this function has a memory leak because the memory that is allocated with "a = new int;" is never deleted and can never be (it is unreachable memory).

Most importantly, in C++, it's considered very bad practice to allocate memory inside a function and give away a pointer to that memory as a return value, expecting the caller to know how to delete that memory. This might be OK in Java (because Java's GC holds your hand like a little baby), but that's just an undesirable side-effect of garbage collection (it makes people forget that in any language, garbage collected or not, it's poor coding practice to do this).

The usual solution in C++ either something like this:


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

The code you posted would indicate that fourvector is a class derived from the class threevector. The constructor of fourvector simply forwards the one_two_three parameter to its base class constructor.

Remark: "I have seen this syntax used for the constructor of the fourvector:"
Run! Just run away from this code! There are so many things that are wrong with it that its not worth wasting time correcting it. Just run, before it poisons your mind.

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

"with user responsibility" == "bad design"

Don't use that solution, it is bad, it violates coding standards, it is cumbersome to implement correctly, it is unmaintainable, etc. etc. Just don't do that.

The second solution is already a lot better, it's easy, safe, maintainable to some degree, and a very common way to do it.

The third solution is to throw exceptions if the stack is full (or popped empty), but, depending on the style/constraints already adopted by your project, it might be appropriate or not.

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

You should probably read this.

Basically, you can't really split template code in the traditional hpp/cpp files. This is because templates don't get compiled until they are used ("instantiated"). So all the code in the cpp file basically gets ignored by the compiler because it doesn't find, in that translation unit, an instantiation of the class template.

So, you basically have to put all the code in the header file (it doesn't have to be inside the class declaration, it just has to be in the header file). Also, a quick fix is to just #include the cpp file at the end of the header (within the include guards!). You will also have to declare all those functions with the "inline" keyword to avoid certain linkage errors if the same template is instantiated in different translation units.

Another option, which is often less convenient is to use explicit instantiation in the cpp file, as such:

template class BinaryTree<int>;

But this means that you have to do this for every type that BinaryTree could possibly be used for (which is not very practical or scalable, and kind-of defeats the purpose of templates). Also, it will make the cpp very long to compile, but you won't have to recompile that template code again after.

EDIT: Rereading your question I just spotted the obvious:

binaryTree tree();

This is illegal syntax in C++ because it will be interpreted as a function declaration, not a constructor call. …

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

Threading facilities can be found under Boost.Thread. These are essentially the libraries that will form the basis for the upcoming threading standard libraries in C++0x, so better get used to those functions/classes for now, until the standard ones come out. And they are cross-platform, so it doesn't matter much whether you are using Windows or Linux (except that performance of certain things are different from platform to platform because they have different kernel implementations).

You will find examples, on the link, on how to use mutexes.

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

@rubberman: Even better, using the C++ function for sorting: std::sort from #include <algorithm>.

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

Learning a programming language involves two things: the syntax and the programming paradigm. The syntax includes all the little rules like = is an assignment and == is a comparison (in C/C++ and related languages), operator priorities, keywords, declaration syntax, etc. These are usually trivial to learn or look-up when in doubt. But, surely, some languages have a more cryptic syntax than others (and that is usually quite subjective). C++ is generally pretty straight-forward for syntax (although there are a few syntax oddities in C++, like trigraphs, the declaration-over-statement rule, or function pointer type declarations), and many languages are strongly influenced by C++'s syntax (so C++ is a good syntax to know, and know well).

Learning the programming paradigm is far less trivial. As opposed to syntax which is about translating your mental image of a program/algorithm into working code, the programming paradigm is about how you construct that mental image of the software, i.e. it's the mindset with which you tackle a problem. C++ is very good for this because it is already a multiple paradigm languages (native support for functional, procedural, object-oriented, generic, and meta-programming paradigms, and supports almost any other paradigm via an appropriate Domain Specific Embedded Language (DSEL) library).

So, I would say that "to master all languages" really is not that important. It is really much more important to master all programming paradigms and coding styles, because it is the way you choose to solve a problem, based on the most appropriate paradigm …

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

Your call to srand() cannot be put in the middle of nowhere like that. You need to put it inside a function body. The common options are at the very start of the main() function, or in the constructor of whatever class you have that needs rand().

EDIT: You should also include <cmath> instead of <math.h>, and only <ctime> not <time.h>.

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

Try changing the name, maybe there is something that already has that name.

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

I'm not sure what's going on, but this looks like some strict syntax issue only (i.e. your compiler is a bit capricious). Here are a few tips that can help:

- If you get some expected ';' after an #include statement, just add a ';' on an empty line following the #includes.
- Finish off your class definitions with a ';' after the closing curly brace of the class definition (i.e. class Foo { }; ).
- Don't forget to leave an empty line at the end of all your source or header files (this is actually required by the standard, but few compilers enforce the rule).

Also, make sure you are compiling in C++, and not some extended language like C++/CLI.

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

>>By the way I am using turbo compiler 3.0
OMG! That's a 20 year old compiler! This is archaic! Please consider switching to something newer. With that compiler, I'm doubting you could even compile whatever code you would like to compile, "within a C++ program" or not (whatever that means, as rubberman has pointed out). Consider maybe MinGW GCC, it is free and always reasonably up-to-date.

jonsca commented: This always bears repeating. +7
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Try removing the sortScores call, because I don't see anything wrong in the avg function. The average should be the same whether the list is sorted or not, so that will tell you if the error is in sort or in avg (and I would bet it is in sort).

Note: your loop is a bit different to what people normally use to iterate through an array:

#include<iostream>
using namespace std;

double avg(double *scores, int numScores)
{
  double total = 0.0;
  double average;
  sortScores(scores, numScores);

  //this is the most usual way:		
  for(int count = 0; count < numScores; ++count)
    total += scores[count];

  //people sometimes do this too:
  for(double* scores_end = scores + numScores; scores != scores_end; ++scores)
    total += *scores;

  average = total / numScores;
  return average;
}

Both styles for the for-loop are equivalent to each other and equivalent to yours, but yours is a bit redundant (either you increment the pointer (or iterator) or you increment an index, not both).

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

I'm guessing the point of this program is not to use an integer to store the values and then add them to get the result. Right? Because in that case, the program would just be:

#include <iostream>
using namespace std;

int main() {
  int a,b;
  cout << "\nEnter first number: "; cin >> a; cin.ignore();
  cout << "\nEnter second number: "; cin >> b; cin.ignore();
  cout << "\nThe result comes to: " << (a + b) << endl;
  return 0;
};

Now, are you required to use char arrays? If you are, I find it a bit sadistic on the teacher's part. In C++, we use std::string for things like that because it's so much better.

If you are forced to use char arrays, there are a few things to know. First, don't abuse the strlen() function. This function loops through the characters until it finds a null-character. It's just a waste to compute this more than once for a string. Compute it and store it in a local variable, don't recompute it over and over like you do on lines 52 to 66 for example.

Second, don't make functions that allocate a char array and then output a pointer to it. That's just a recipe for disaster. Preallocate the "output" string and pass the pointer as a parameter (like all str functions do (strlen, strcpy, strcmp, substr, etc.)).

Third, anything you allocate needs to be deallocated (i.e. every new-statement has to be matched with a …

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

I don't know of any, I don't do .Net at all. But I just wanted to point out that what you seem to be looking for is called an "obfuscator". Search ".Net Dll obfuscator", you will find plenty (free and not free).

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

I think the answers so far are very good, but I could have a few things to add, because I love answering good questions like this.

>>Memory and CPU efficiencies are important

Then don't use the function at(i) like you do at line 16 and 36. The at function includes bound-checking which is a waste when you are just looping through. That's just a small remark. Use the [] indexing operator or iterators instead.

>>1. Memory leak. Does the order in which the class destructors are called ensure that there is no memory leak? When the collection destructor is called, I needed to "delete sets->at(i)" to deallocate the Set objects allocated elsewhere, but does the Set destructor get called, or does a memory leak result?

To answer the question: You did it correctly in the sense that memory won't be leaking, as far as I can see. The destructors for the sets will be called and so will the default destructor of the segments. If you want to check for memory leaks, run your program in Valgrind (I would suggest you run it on a smaller amount of "test" data, both because if you do have a leak, you don't want to have massive leaks reported, and because valgrind is a virtual machine that is slow because it does a lot of bookkeeping to allow you to trace back the leaks, post mortem). For memory issues Valgrind is the tool to use.

On the grander …

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

I don't know what made Nichito and caut_baia assume that you are using the win32 API, so let me give a more platform agnostic solution.

It is pretty simple really. First of all, your logger should give a no-throw guarantee for almost everything it does. This could be a hard requirement to fulfil depending on the complexity of your logger, which should be a simple as possible (and you might have to use low-level C-style programming to control that).

In your implementation of the logger, you should no let any exception escape and you should verify any error codes you might get (if you are using API functions that rely on error-codes like win32). If you do get errors, you should just deal with them in the logger by reverting to a less convenient but more likely to succeed mechanism for reporting the error (that could include a MessageBox or std::cerr, or even exit()). You can also try more than one (go from the most desirable/convenient to the worst (i.e. exit())).

So, your logger could do something like this:

class Logger {
  private:
    //fall-back error report:
    void log_cerr(const std::string& aMessage) throw() {
      bool succeeded = false;
      try {
        if(std::cerr << "ERROR: Logger Failure! Fall-back report: " << aMessage << std::endl)
          succeeded = true;
      } catch(...) { }; //catch-anything, do nothing ("succeeded" remains false)
      if(!succeeded)
        exit(); //last resort!
    };
  
    std::ofstream outFile;
  public:
    Logger() throw() : outFile("error.log") {
      using namespace std;
      outFile.exceptions(ofstream::eofbit | ofstream::failbit | ofstream::badbit); 
    }; 
    
    void …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You are misusing the sizeof() operator. This operator is computed at compile-time, not at run-time. So, it cannot be used for getting the size of anything that was allocated dynamically (btw, dynamic is usually a synonym of "at run-time" in C/C++). Basically, it outputs the memory required to store the variable, at compile-time. In the case of a dynamically allocated array, that means the size of the pointer type, not the size of the array that it points to. This also goes for the string type (and equivalently C-style strings), sizeof() is not a proper way to get its size (as in, it's number of elements or characters).

So, at line 6 (in the erroneous code), the allocation should be p = new char[line.length() + 1]; (the + 1 is to store the null-character that terminates a C-style string), and, similarly, at line 10, you should have strcpy_s(p, line.length()+1, line.c_str()); (and it should also be that way on line 22 of the working code, even though it doesn't crash, you are doing useless copying of garbage data).

As Greywolf333 pointed out, don't forget to deallocate any memory you allocate with new (i.e. using delete[] p; ) once you are done with it of course.

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

Pretty much in my order of preference (note that it might not be yours):

1. Code.Blocks (free, with MinGW GCC)
1. Visual Studio 2010 (or Visual C++ Express (free))
2. Eclipse C++ (free, but you need to install and configure your compiler of choice yourself)

Things to look for that I find useful is fast background parsing that can highlight the code (i.e. recognize variable names and types, and color them such that you see right away if you made a typo by checking if it got highlighted correctly), code completion (i.e. you type the start of a variable name or type and it completes it for you by scanning (efficiently) your code-base), good support for external build systems (like cmake or makefiles), good debugging features, etc. Mostly, Code.Blocks and Visual Studio achieve this fairly well (I do find that Code.Blocks' code completion and background parsing is a bit slow though). I actually prefer, above all, KDevelop 4, because it scores the best on all the above criteria, but it's only for Linux.

As for compilers:
1. MinGW GCC 4.5 (or newer) (there is a good deal of improvement from 4.4 to 4.5, and 4.6)
2. Comeau (not free, but cheap, great standard compliance (better than any other compiler for this))
3. Intel Compiler Collection (ICC) (if you can afford it, it has great performance and great compliance, …

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

>>What programs did you make after learning these things and can you recommend me what I should write with knowledge of these features?

Some of my early programs, while at your level, mostly revolved around 3D graphics (simple 2D/3D computer games, simple physics engines, collision detection algorithms, procedural generation of landscapes and other natural artifacts, particle systems, dynamics simulator and editor, etc.). The best project for you is the project YOU are most interested in (I'm a math junky so that drove the type of programs I played around with, and still work on today).

It's always difficult to keep yourself focused when you are doing programs as a hobby (not for money or a university degree, or both). To maximize your chances of not getting bored or burnt out, you should first make sure you have a good interest in the field (that drives the "impress yourself" reward-system), and second, try to pick a project that is very incremental and implement it incrementally so that you see new results every step of the way (it also eases the debugging/testing process a lot!). Another thing that can boost your focus and engage you more into the project is to do it with others, with friends and/or through an open-source team-project.

Following a level of knowledge in C++ that makes you feel confident enough to move from "textbook example" kind-of code towards a more concrete project, I think the natural next step is to learn to use other …

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

Your constructor declares a local array of size "size" called wordList. It will not initialize the data member of DictHash called wordList. I would assume that you use std::map for the type of wordList. In that case, it should work without initialization. Otherwise, you need to use an std::vector for wordList, and initialize it as follows:

//constructor
DictHash::DictHash(int size) : wordList(size) 
{
    
}

What is after the : is called the initialization list, and it is basically where you call all the constructors of all (or some of) the data members of the class, with whatever parameter they need.

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

Well, let's put things straight here. If you can easily do something with a loop, you do it with a loop. Clearly it will almost always produce less stack footprint, faster code and easier for the compiler to optimize, but that's not the point of my question.

Nor is my question about whether the first piece of code you showed or the last is easier to optimize automatically for the compiler. Obviously, the last is much harder, but I'm always amazed at how deep in the DU-chain the compilers can go, possibly, in this case, the compiler would reuse the same string object on the stack, but might do more destroy-construct in the loop that wouldn't be required in a hand-rolled loop. In other words, it would optimize to something like this:

void traverse(Node* n) {
  while(n) {
    std::string s = "Test";
    process(n, s);
    traverse(n->left);
    n = n->right;
  };
};

//instead of the obvious:
void traverse(Node* n) {
  std::string s;
  while(n) {
    s = "Test";
    process(n, s);
    traverse(n->left);
    n = n->right;
  };
};

Another thing that my question is not about is this. I'll use the single linked list kind of example. Say you have two functions, which are essentially a traversal, one forward, one in reverse, but both are given the head (or start) node:

void traverse_forward(Node* n) {
  if(n) {
    process(n);
    traverse_forward(n->next);
  };
};

void traverse_reverse(Node* n) {
  if(n) {
    traverse_reverse(n->next);
    process(n);
  };
};

The former uses a tail-recursion, the latter doesn't. I would say …

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

You need to make your arrays of size 4, not of size three. This means, your array declarations should be:

float IC[] = {1,1,1,0}, K[] = {0,0,0,0}, K1[4], K2[4], K3[4], K4[4]; //notice 4 here.

You basically has a problem of overlapping memory (the last element of K1 was at the same memory place as the first element of K2, as an example, but it could involve different elements). I'm pretty sure that would fix your problem.

>>K3[4] = 0.49999995230. Why does it round?
That's completely normal. You are using a "float" variable which is not expected to have better precision than to the 7-8th significant digit. This number is exactly what you would expect to get. You could use "double" for more precision (15 significant digits), but it's not sure that an Arduino uC would support that (sometimes floating point operations are not even supported at all).

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

@arkoenig: Great, clear explanation. It had occurred to me that there was a tail-recursion optimization in the code you posted. But I think that your average COMP 101 grader would never pick on that (even if he saw that, he wouldn't expect it to be intentional).

Just a question. Is tail-recursion optimization even relevant anymore? Today, compilers are much more clever than they used to be. I mean, I tried your code versus the obvious shorter version that doesn't do tail-recursion. From looking at the assembly listing, in either case, it's obvious that there is no stack wind-up and the recursive calls turn into jumps (that's with GCC, of course, but I would expect any modern compiler to do the same). At best, the tail-recursion version saves a few simple instructions. Is it really worth the contortions?

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

The * (star) that designates a pointer is linked to the type, not the variable name. That's why I prefer the convention int* ptr; instead of int *ptr; , just because it makes it more obvious that it is a variable of name "ptr" which is a pointer to an integer. In other words, the star qualifies the type, not the variable.

With this in mind, what is wrong with your implementation is that when you set the initial value of your static data member "m", you are putting the star in the wrong location (next to the name, not to the type). So here is the solution:

int* myclass::m = NULL;

That will make it compile, but there are definitely things that are wrong with your implementation, namely, you are dereferencing pointers that were never initialized to point anywhere (i.e. l and m).

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

You can think of it in terms of std::vector. This is a reasonable guess at how it is implemented (probably not actually uses a std::vector, but it is the basic example of a constant-amortized dynamic buffer):

//here, I'm just replacing the string with a vector of char to show how it is done:
std::istream& operator >>(std::istream& in, std::vector<char>& s) {
  char c;
  while ((in.get(c)) && (!isspace(c)))
    s.push_back(c);
  return in;
};

Since the dynamic array that is contained in std::vector is constant-amortized, the size will grow exponentially until it doesn't need to grow anymore. That is, IMO, the most likely implementation (or at least, a slightly more sophisticated version of that).

If you are talking about the buffer on the side of the IO stream, then that is a slightly different story. In that case, buffers are often implemented as rolling queues (i.e. you have a "fixed" size buffer with some index for the start (where the get pointer points to) and an index for the end, and basically, you make the start-ptr chase the end-ptr round and round the array, it is only if the end-ptr gains on the start-ptr that you need to allocate more memory).

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

@arkoenig: I understand that the OP didn't show enough effort towards solving the problem himself that it shouldn't be dignified with an answer. You could just have said so. With all due respect, posting a bad solution and implying that he should make it even worse so that he can hand it in without suspicion is a bit of a nasty trick, IMO. It sort-of locks him out of finding the actual solution to the problem, which I won't post, obviously, but I just wanted to point it out.

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

Well, the iPhone uses Objective-C. And, as far as I know, it's not trivial to try an use C++ to program for it (Objective-C is an Apple thing, and we all know how monopolistic Steve Jobbs is, same as Bill Gates at Microsoft, no real difference there).

Are you far from being able to use an SDK? No. I would probably recommend a bit more ground work, at least on the STL and good OOP knowledge. But after that, you can jump right into it. Using SDKs (and multiple ones) to essentially "assemble" an application is a great way to learn and do some interesting (visual) stuff. And it really isn't that hard, but it can require some amount of patience when reading function/class documentations and troubleshooting.

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

>>Could you create a class inside a function, define its functions then return the class to access its functions?

Humm, you can't return a class, only an object (via a pointer). A class inside a function is called a local class. A local class has no linkage. This means that its functions cannot be called from outside the function that encloses the local class. I guess, you should still be able to call virtual functions from outside the enclosing function, provided that these are virtual functions of a base class that is not itself a local class (duh!) (and, frankly, I don't even know if that would even work because I've never tried and never seen any code that does that, even plain local classes are so rare that many people don't know about them at all). Basically, a local class does not exist outside the body of the function (literally, since it has no linkage).

>>Also when does C++0x come out?

I believe the plan is for it to come out before the end of this year, but the original plan was for 2008, so I wouldn't be so sure that it will be out by this year.

>> and how do we get it?

You can get it already on most recent compilers. Of course, it is not the official new standard because it hasn't come out, it's the draft version (which is expected to be pretty much the same thing). If you …

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

I don't think you could possibly find a book that talks about Lambda expressions in C++, because they are not even officially supported yet (but the new C++ standard will be there by the end of this year, at least, everyone is crossing their fingers for that).

From reading the list of chapters you posted, I think I would just recommend you get another book. Half of the book is about MFC, which is being phased out even in the Windows-only world (which is a world that is also shrinking rapidly). And only one chapter on the Standard Template Library! That can't be serious! But you should at least read that chapter before you let go of the book and go for a better one (which I can't recommend, cause I haven't learned through books and never read any other than the most advanced ones, I'm sure others will, or look at this thread).

If you have read through this book already and done enough hands on to get a good grip of the language (and I mean a lot!), then I would first recommend you go through all the C++FAQs. This is a good run-through of all the little intricacies of C++. By then if you feel up for it, go for "C++ Coding Standards" (Sutter & Alexandrescu) and then "Modern C++" (Alexandrescu) (these two, along with the actual C++ Standard documentation, are the only books I ever refer to).

Also, get …

L3gacy commented: good tips +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Let me take this in the reverse order:

3) Declaring a template function outside a class
That's easy, the syntax is as follows:

class Thing
{
    public:
    template <typename T>
    T thingy();
}

template <typename T>
T Thing::thingy() {
  //blablabla...
};

If Thing is also a template:

template <typename T>
class Thing {
  public:
    template <typename U>
    U thingy();
};

template <typename T, typename U>
U Thing<T>::thingy() {
  //blablabla...
};

2) Creating a class within a function
This is allowed in C++, but fairly rare. The syntax is also very straight-forward:

class Abstract
{
    public:
    virtual void do()=0;
}
Abstract* getClass()
{
    class Derived : public Abstract {
      //blablabla...
    };
    Abstract* ret= new Derived(); //this is very ugly, but allowed.
    return ret;
}

EDIT: Thanks to firstPerson for pointing out a little mistake I made about the not returning a reference to a local variable of class Derived. In this case, you would need to allocate the function dynamically and return a polymorphic pointer (or better yet, a smart-pointer).

But there are special rules about such classes, for instance, they cannot be class templates or have function templates in them. I think that you also cannot use any of the variable of the local scope of the enclosing function in the class. Etc. etc. You can read up on it by googling.

1) Creating a function within a function
This is not (currently) allowed in C++. Of course, you can have …

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

I guess it could be implementation dependent, but you can pretty much assume that the std::string is implemented as a std::vector of char (with additional functionality of course). So, the size of the buffer it allocates to store the string literal will probably be either the exact number of characters (and probably also adds a null-character just for simple conversion with c_str()), or it will be the smallest power of 2 which is still greater than the size of the string literal. The former might occur just because the literal initializes the string's initial size. The latter is what is expected most of the time, of course, it could differ. Frankly, it's not really that important.

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

C++0x will include a new syntax option for the for-loops that is essentially the same as the foreach. Additionally, the use of for_each and many other <algorithm> will be made a lot nicer with the addition of Lambda expressions.

Here is a glimpse:

#include <iostream>
#include <algorithm>

int main() {
  int my_array[5] = {1,2,3,4,5};
  //this is the new for-loop syntax that can be used instead of for( ; ; )
  for (int &x: my_array) {
    x *= 2;
  };
  std::for_each(my_array, my_array + 5, [](int& x) { std::cout << x << std::endl; });

  //or equivalently, with Lambda expressions:
  std::for_each(my_array, my_array + 5, [](int& x) { x *= 2; });
  std::for_each(my_array, my_array + 5, [](int& x) { std::cout << x << std::endl; });
};

The above compiles fine using GCC 4.6.0 (experimental) (which is available btw, but you have to compile and bootstrap from source (can take a couple of hours to do)).

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

Boost.Variant is a small library that is especially made for this case you are describing. It is basically a discriminated union, as vijayan121 suggested, but it is already implemented for you.

Of course, in the case of int and char, it is somewhat useless since they are both integer types, and I doubt that you can easily define overloads that won't be ambiguous at times. I would be just as good to just store it as an integer and cast it to char whenever you need. But I assume, this is a simple example for something a bit more complex.

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

>>But the thing is would you be limited to exactly those bits? So no custom failure would work.

What custom failure?

There are three failure cases for the istream:
- eofbit: when the stream reaches end-of-file (I guess cin will never throw that one)
- failbit: basically a failure to perform the reading operation.
- badbit: some other problem (e.g. the source of the stream is in a bad state).

There are no "custom" failures, these are just the failures that the standard has decided on for the implementation of istream. The "exception()" function simply tells the istream which error cases should throw an exception and which should not (and thus, will be signaled by the internal state flag instead, i.e. an error-code mechanism).

Custom failures could mean two things: either you are implementing your own kind of istream and have other failures to report, or you have some special items that can be read off any istream which have failures of their own to report. In the former case, since you are implementing your own istream class (or derived class), you are free to throw any exception you like. In the latter case, you would just throw your custom exception in the read operator >>, see my last post.

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

The first observation is that you are using floating-point arithmetic (e.g. 2.6 * M - 0.2). The Zeller algorithm is based on the fact that integer arithmetic is used. In other words, (D / 4.0) is not equal to (D / 4), the former is in floating point arithmetic and the latter is in integer arithmetic, and they will yield different results, even when the floating-point value is rounded or cast to int.

According to this wiki article, the Zeller's algorithm already takes the leap years into account. You don't need all these if-statements. Why don't you implement the formula as is?

To convert the input such that it fits in the formula, all you have to do is check if the month is 1 or 2, in which case, you should make the month 13 or 14, respectively, and then decrease the year by one. Then, the formula should work:

int CalcDayOfWeek()
{
  if(month < 3) {
    month += 12;
    year--;
  };
  int K = year % 100;
  int J = year / 100;
  
  return (dayOfMonth + ((month + 1) * 26) / 10 + K + K / 4 + J / 4 + 5 * J) % 7;
};

Finally, according to the wiki, the day of the week is such that 0 = saturday, not sunday.

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

I'm happy that L7Sqr pointed out that IO streams have exceptions as an alternative to those ugly while-loops and successive if-statements. It's certainly the preferred way to go in many cases, and many people, even experienced programmers, forget about this or never knew at all.

You can also use exceptions as a validation mechanism that integrates very nicely with stream exceptions. Here is an example where you would like to force the user to write their names (which, I assume, would not contain numbers or punctuations):

#include <exception>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

struct invalid_name : public exception {
  const char* what() const throw() { return "The name entered is invalid!"; };
};

struct full_name {
  string first_name;
  string last_name;
  full_name(const string& aFirstName = "John", const string& aLastName = "Doe") : first_name(aFirstName), last_name(aLastName) { };
};

istream& operator >>(istream& in, full_name& fn) {
  in >> fn.first_name >> fn.last_name;
  if((count_if(fn.first_name.begin(),fn.first_name.end(),::isalpha) != fn.first_name.length()) || 
     (count_if(fn.last_name.begin(), fn.last_name.end(), ::isalpha) != fn.last_name.length()))
    throw invalid_name();
};

int main() {
  int the_age = 0;
  full_name the_name;

  cin.exceptions( std::istream::failbit );
  while(true) {
    try {
      cout << "How old are you?" << endl;
      cin >> the_age; 
      cin.ignore();
      cout << "What is you full name?" << endl;
      cin >> the_name; 
      cin.ignore();
      break; //if it got to this point, it means all was valid.
    } catch (istream::failure & e) {
      cout << "Exception: " << e.what() << endl;
      cin.clear(); cin.ignore();
    } catch (invalid_name& e) {
      cout << e.what() << " Please re-enter the information..." << …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There are indeed special rules about virtual functions, especially when they are inlined. But none would explain what you have observed. Basically, the special rules are about allowing the compiler to by-pass the dynamic binding (vtable lookup) in cases where the object type and thus the virtual function call is obvious.

First of all, if you have Child myChild; myChild.MyFunction(); , then this is never going to be a virtual call. In that case, the type of myChild is an object, not a reference or pointer, there is no reason for the compiler to delay the binding of the call to run-time, it will be bound at compile-time (i.e. the function will not be looked up in the vtable).

Second, there are cases where even if the call originates from a reference or pointer to an object, the compiler is also allowed to bypass the vtable if it is able to figure out what the type of the object is. For example:

Child myChild;
Parent& myParent = myChild;
myParent.MyFunction();

In this case it is quite likely that the compiler will understand that myParent actually refers to an object of type Child and will call its member function directly, bound at compile-time, bypassing the vtable. The more complex the situation is, the less chance there is for the compiler to be able to do this, it just depends on how clever the compiler is (and I guess the level of optimization performed). For instance, with GCC 4.6, the …

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

What you need to do is dereference the y pointer. There are a couple of ways to do it:

1) the * (star) is a dereference operator when applied to a pointer variable:

int x = *y; //gets the value that y points to.

2) the is a dereference operator that also allows you to get the value at "i" integers from the address stored in y (i.e. this indexes into an array):

int x = y[0];  //gets the value that y points to.
x = y[2];      //gets the value 2 integers after y[0].
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@Michael_Tanner:

I'm curious. What compiler did you use which allows the original code you posted to compile? Please provide the version number too.

I've been googling a little bit on the subject and I am now pretty much convinced that a standard-compliant compiler should not allow this to compile. Maybe it is a bug in the compiler or a very esoteric one.

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

@arkoenig:
>>And even if it were, casting it to myclass* yields an rvalue, to which you can't assign.

rvalue-lvalue qualification is not the same as cv-qualification. You can have a const or non-const, lvalue or rvalue variable. The standard specifies that the this pointer should be "non-lvalue", which is really weird IMO, because "non-lvalue" is a ISO C term, not a C++ term, it is not defined anywhere in the standard. One interpretation of non-lvalue is simply that it is a const lvalue in C++, the other interpretation is that it is an rvalue. If the OP's compiler chooses to take the first interpretation, then the const_cast of the this pointer would be acceptable under conversion rules that apply to const_cast. In that case, the this pointer is a const lvalued local variable (or a const lvalued reference), so the const_cast strips the const, but this is already just a local variable, and thus, setting it to NULL is just meaningless because that won't have any effect outside the member function.

But you are right, if the OP's compiler accepts the code he posted, it surely means it is not a good compiler, but I'm not sure it actually breaks the standard. I can easily imagine why the compiler would choose to do this. Imagine, in a const member function, you attempt to do a const_cast on a data member to be able to modify it (of course, that's ugly, but allowed). Then, if the this pointer …

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

>>i cannot find a good implementation for it !!

That's a good thing! The point of a homework problem is not for you to go out and google for a ready made algorithm. Nor is it for you to come to a forum like this one, paste the assignment problem, and wait for someone to post a full piece of working code.

The point is that you should think about it, try to solve it, make the code work. If you show that you have tried your best at coming up with some working code by yourself, then you can ask for hints on this forum. Don't expect complete code after demonstrating no efforts, that won't benefit you and that's why we wouldn't post that.

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

**PLEASE USE CODE TAGS** it's horrible to read this post.

I did manage to spot this: char *p = strtok((char*)s.c_str(), " "); You cannot use strtok() with an std::string! What is returned by c_str() is a read-only char array. The c_str function returns a constant pointer, but it should return a constant pointer to constant, meaning you should not modify the characters it points to (the reason why it doesn't is for compatibility with C).

Basically, the C++ std::string is not anything like a C-string (const char*) and should not be used as such. The c_str() function is just provided for convenience of being able to _read_ the string as a C-string, it is not for writing. It might work, but that is just accidental.

C++ has it's own set of functions for extracting different things from a std::string, and those are the functions you should use. Most of them are collected in an object of class "std::stringstream" (in #include <sstream>) which can be used in a similar fashion as cin or cout (or any other IO stream), but from or to a string instead of the console or file. Here is how to extract that first token from the C++ string:

std::stringstream ss(s);   //create a stringstream from the string s that you have.
std::string p;             //create a string to hold the first token.
std::getline(ss, p, ' ');  //extract string up to the first space character from ss.
WaltP commented: So I added CODE tags for him. Did it help? +15
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you need the "add" or "union" function to be adding or uniting two sets, then you need to make the function parameter a set:

template<class T>
class set
{
 public:
  void add(const set<T>& otherSet);
  void union(const set<T>& otherSet);
 private:
}
#include "set.template" //that's weird, btw.

And similarly in your set.template.

If you want your functions to work on individual components of type T, then make T the parameter type (well, const T&). But, then, you have to pass an element to the function, not a set.

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

This is exactly what exceptions are used for. If you throw an exception in the constructor (whenever some condition is not fulfilled or something failed), it will cause a stack unwinding which will effectively unconstruct your object (not call its destructor, but literally back-track all the code in the constructor). The exception is then reported to the user-side code which will then be responsible to dealing with the situation. That's the only way and the best way to deal with a constructor that could fail.

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

The stride of a pointer is determined by the sizeof the type to which it points. And the sizeof a type is fixed at compile-time. If you can't change the type it points to, you can't change the stride. End of story.

The attempt you posted achieves nothing to this end, because it is impossible.

You would need to change the pointer type into an iterator for which you can change the stride at run-time:

class pixel_iterator {
  public:
    enum pixel_format {
      rgb = 3,
      rgba = 4;
    };
  private:
    char* ptr;
    const pixel_format stride; //const will make this class a bit faster.
  public:
    pixel_iterator(char* aPtr, pixel_format aStride = rgb) : ptr(aPtr), stride(aStride) { };

    char& r() { return ptr[0]; };
    const char& r() const { return ptr[0]; };
    char& g() { return ptr[1]; };
    const char& g() const { return ptr[1]; };
    char& b() { return ptr[2]; };
    const char& b() const { return ptr[2]; };
    char& a() { return ptr[3]; };
    const char& a() const { return ptr[3]; };

    pixel_iterator& operator++(int) { ptr += stride; return *this; };
    //.. all other operators that are relevant.
};

You have to replace the C++ mechanism that increments pointers by the sizeof the type they point to, and the only way to do that is to replace the pointer with a custom object.