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

>>Hey mike the "-> bool" specifies a return type?

Yeah, that's the Lambda expression syntax.

It is also a new way to specify return types for normal functions, with the "auto" keyword. As so:

auto my_function() -> int {
  //..
};

This is especially useful for function and class templates where the return type can be contingent on the parameter types in a non-trivial way.

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

While you are using C++0x, then you might as well do:

my_list.remove_if( [](int x) -> bool { return x == 4; } );
Jsplinter commented: ah, right lambdas! thank you +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I agree with Narue.

Collecting a bunch of "fundamental" types into one header file is fairly common, as long as those types constitute a cohesive group of related types. The fact that you cannot find a better name than "types.h" sort-of hints to the fact that they do not form a meaningful cohesive group (btw, you will need a header-guard that is more specific than TYPES_H, otherwise you might have problems later). In theory, if you stick to the one-header-one-class rule, then this whole thing of circular dependency won't be a problem at all, but it certainly can seem a bit wasteful to have one header for one typedef. But again, if later you decide to make the GrassType a bit more complex (some user-defined class), then it will be more convenient if it is in its own header.

Collecting many types into one header can also cause great grief to the building process. The header file in question sort of becomes one file on which a huge amount of other files depend on. This means that anytime you change something to this file, it will trigger a complete rebuild of all code, including stuff that is absolutely not related to the change that you made. This can get really annoying at times, if the code-base is large. The more fine-grained your headers are, the less unaffected code you have to rebuild when small modifications are made.

But, definitely, the situation seems to mandate the use of …

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

>>Why is it a bad idea to use the std namespace for my new functions?

You should not put anything in the std namespace. There are only very rare (and advanced) reasons to put anything in the std namespace.

And there is nothing special about the std namespace in this regard, the same goes for any library you use. Any good library will have all its things in at least one top-level namespace (like std, boost, cv, etc.), yours should too. Generally, a library is meant to be _used_, meaning that elements of its namespace are invoked (classes and functions). Libraries are rarely meant to be extended by expecting or allowing a user of the library to add things to the library's namespace. The C++ standard library is one such library which is not meant to be "extended" by the user.

You have to understand that entering the namespace of a library is like entering inside the guts of the library, you get exposed to all the complex inner-workings which are fine-tuned to work without your "extensions". And "using namespace .." is like spilling the guts of the library all over the place.

>>If all of my functions have names which are different than the names of std functions, it is no harm, right?

So.. you know all the names of all the functions and classes (including those which are implementation details, like helper functions), and that is, for all implementations of the standard library, …

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

nmaillet is correct.

But in response to:
>>Also if you see anything in my code that needs to be fixed feel free to tell me about them.

I don't see anything that _needs_ to be fixed, but certain things could be made better.

First, think hard before you use the var-args feature. This is a C feature that is not type-safe. Nothing prevents someone from constructing a Vector and give it a bunch of crazy parameters that will corrupt everything. Type-safety is a blessing for robustness, by-passing type-safety is not something to be done lightly. I think I understand what you are trying to do with this constructor: be able to construct a vector by giving it a list of values. Personally, I would go with the good old fashion way:

Vector(T q1) {
     BOOST_STATIC_ASSERT(D == 1);
     //..
   };
   Vector(T q1, T q2) {
     BOOST_STATIC_ASSERT(D == 2);
     //..
   };
   Vector(T q1, T q2, T q3) {
     BOOST_STATIC_ASSERT(D == 3);
     //..
   };
   //.. etc. for as many as you like.

Of course, if you can use C++0x (upcoming standard), then you can simply use the initializer_list. As so:

Vector(std::initializer_list<T> q);

Second, if you know the length of the vector from a template argument (D), then why don't you make your vector class store a static array? Why pay the price of dynamic memory allocation when it is not necessary? I highly recommend you do that, to actually make that class useful in any way.

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

All you need is to rewrite the value with 2 digit precision after the dot.

Look at setprecision. There are examples that do exactly what you need.

Just read the numbers from the input file, and write them to the output file with the setprecision functionality.

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

>>If we say rvalue, isn't it going to change in C++0x

Not really, C++0x introduces an additional type of reference, i.e. a rvalue-reference (with the double ampersand). It doesn't change the fact that you cannot bind an rvalue to a non-const reference, in fact, it is very useful because it allows overloading based on rvalue/lvalue distinction, which is not possible in C++98/C++03. As follows:

void foo(double& d) {
  //some code that uses d as a reference to an lvalue.
};

void foo(const double& d) {
  //some code that uses d as a const-reference to an lvalue.
};

void foo(double&& d) {
  //some code that uses d as a reference to an rvalue.
};

The above is not possible in the current standard because, since you cannot provide the third overload, if an rvalue is passed to the function, it will bind to the const-reference, and you cannot distinguish between a const-ref to an lvalue or to an rvalue. So, you cannot safely take the address-of the reference because it could be an address to a temporary. In C++0x, you can be sure that the const-ref will be referring to an lvalue (otherwise the rvalue-ref overload would have been selected), and thus, taking the address-of is safe.


>>Can you please give an example for that?

See this gotw article, under "The Language Lawyer" (the others could be filed under what I mentioned as "other nasty hacker's tricks").

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

The parameters of a function only exist as long as the function is executing. When the function has finished, its parameters disappear. They don't need to be "reset" before the second call. When you call the function, you provide the arrays it should work on, and the second time you call, you just provide different arrays it should work on and it will work on those arrays instead. Function parameters are not global variable that exist all the time, they simply take the values that are passed to the function when it is called, then can be used inside the function, and when the function is over, these variables disappear (literally). In your specific case, the parameters are arrays, so they are passed as pointers to the first element of the array, at every call, they are assigned to point to whatever array you provided when you called it.

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

First, static local variables are created once, the first time control flows over them. So, for a singleton (which is what CVSystemDLL is) you would only need this as implementation of pInterface->m_pFactory:

static CVSystemDLL* ret = new CVSystemDLL;
  return ret; //let ret be implicitly cast to void* (don't use '(void*)ret')

Furthermore, dynamic memory allocation is not needed, you could do:

static CVSystemDLL ret;
  return &ret; //let ret be implicitly cast to void* (don't use '(void*)ret')

Now, the observation about the (void*) cast is valid at the call-site as well. You should not use the (void*) to cast pointers because the behavior is to perform a reinterpret_cast which has undefined behavior, by definition (C++98 Standard clause 5.2.10/3). The same rational goes for casting the void* back to IVSystemDLL*. This sequence of casts has undefined behavior, especially if it is across a module boundary. To perform the call-site cast, you need to use static_cast, and that's the only option.

VSystemDLL *pSystem = static_cast<IVSystemDLL*>(Plat_GetInterface( "vsys.dll", SYSDLL_INTERFACE_VERSION ));

Finally, what happens in Plat_GetInterface? I suspect you are doing this:

HMODULE dlhdl = LoadLibrary("vsys.dll");
  typedef void* (*InterfaceFactProc)(char*);
  InterfaceFactProc get_fact = (InterfaceFactProc) GetProcAddress(dlhdl, "InterfaceFactory");
  typedef void* (*InterfaceFactoryFuncPtr)();
  InterfaceFactoryFuncPtr fact = (InterfaceFactoryFuncPtr) get_fact();
  void* ret = fact();
  FreeLibrary(dlhdl);
  return ret;

If this is what you are doing, then I am not at all surprised that you are getting an access violation. You cannot use anything that has been obtained from a DLL after you have freed it. That includes pointers to exported functions …

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

The form std::string test("hello"); is called a "direct-initialization". This is essentially a direct call to whatever constructor matches the parameters given. Direct-initialization is the only accepted form in a class constructor's initialization list.

The form std::string test = "hello"; is called a "copy-initialization", because it is meant as a initialization of the new object with a copy of another, and the standard does not permit much else (this will be expanded a bit in the upcoming standard). You will find the relevant clause in the C++ Standard 8.5/14. What is special about the copy-initialization can be summarized (extract from the standard text) to:

If it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression(s) as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.

Otherwise, user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed.

In plain english, it means that the right-hand-side needs …

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

Would I then have to overload the constructor for every single combination of the option parameters? Or is there are way by which I can just have one long parameter list in the constructor, and that if the user doesn't pass a specific optional parameter, that the compiler knows how to parse the rest of the parameter list using just one constructor definition?

This is exactly what the Boost Parameter Library does. You can pass parameters in a simple "identifier = value" comma-separated list, where order doesn't matter, and you can make any of the parameters optional with some default value. Normally, you should be able to program a single function, you won't need overloads. Of course, it is somewhat verbose when you create a function to be called this way because it requires using several MACROs that are very complex under-the-hood (uses Boost PreProcessor Lib.). But, the point is that it makes the call-site syntax simple and clear (which is the point of writing library code: put all the complex construct under-the-hood to expose the simplest and clearest possible interface to the user).

The way I've set things up now is that the user creates the predefined Earth, with all the preloaded settings, and then uses a set-function to reset the value of the mass. Do you have a suggestion as to a better way to go about doing something like this?

Oh yes. There are better ways to do this. Personally, I just use serialization …

m4ster_r0shi commented: This is an awesome post. +5
alwaysLearning0 commented: another great post +4
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I have not heard or seen any book or resources online which are a "generic guide to using external libraries in C++". I think the problem with writing such a guide is the shear amount of possibilities. There are APIs, header-only libraries, source-file-only libraries, different programming paradigms, some have special build tools (like qmake for Qt), etc.

Generally, you need to follow the instructions on the website of the library as best as you can. And remember that some libraries are not extremely well-written, and the author(s) might be overstating the portability of the code (if you hear things like "my lib should compile with any standard C++ compiler", don't trust that because "should compile" means it wasn't really tested, and a "standard C++ compiler" doesn't really exist in practice).

To add to JasonHippy's post, if using binaries, make sure that the binary was not only compiled for the correct platform, but also that it was compiled with the same compiler that you are using. Be aware that there are special steps to take if you need to use a binary that was compiled with another compiler, and it may not be successful at all, in which case, you need to recompile from source code.

A few more pieces of advice:
1) Don't introduce external dependencies which only solve trivial problems, prefer to write your own code from scratch if it's simple enough. I'm not saying you should reinvent the wheel all the time, I'm simply …

kvprajapati commented: Good post. +15
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

LOL! @WaltP: Pretty good timing for this thread! Don't you think?

Yet another example of "I compile this with DevC++ and it doesn't work, but it works with other IDEs like ..".

@OP: I agree with both posters. Stick to one generation of C++ code, that is, the current standard, and standard-only. Follow WaltP's recommendation on that. Don't follow example codes or tutorials that are too outdated or non-standard (and seeing "iostream.h" or "conio.h" is a pretty good indication of that). But I would also recommend you pick another IDE besides DevC++, like Code.Blocks or Visual Studio, and try to pick a recent version.

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

>>By code snippets I mean pressing Tab at the right time and generating a stub for an event handler, an if-block, or something else,
Yeah, I know. I understand you can save typing with that. I personally find it annoying, and rarely useful. But I can understand that it is helpful for GUI code, because GUI library often require a bit of special code.

I do, however, value "code-completion" very much. This is when you type the first few letters of an identifier and the IDE gives a list of possible matches, and simply pressing tab or enter puts the rest of the name. That is very useful because it allows you to have long and descriptive variable names without additional typing effort. And, I would say, this is the primary reason that I use an IDE to code and not an enhanced text editor (like emacs or vim). The problem is, my code is heavily templated (generic programming and template meta-programming) which makes it very difficult for code-completion to work in a timely fashion. So far, I have only found KDevelop 4 to be able to keep up (both VS and Code.Blocks are just too slow and resource-hungry when code-completion is enabled when coding my stuff).

>>BTW, what kind of setup are you using,

Basically, quite opposite to yours. I code almost exclusively on Linux (Kubuntu 11.04). I use KDevelop as an IDE. I use a rolling version of

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

>>Definitely a bunked include path

Try to locate the header files manually in the hard-drive. Possibly, add all the sub-directories to the include path list. Make sure you have all the dependencies met.

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

If under Linux, you can use the "pdftotext" command (from package "poppler-utils"). Then, you can use "libtranslate-bin" package to install a text translator program and use it with "translate-bin" command. So, your problem can be entirely solved by:

$ pdftotext my_file.pdf my_file.txt
$ translate-bin -s google -f en -t fr my_file.txt > mon_fichier.txt

You only need to wrap these two calls in a shell, and you are done.

Ancient Dragon commented: you made it too easy :) +17
alwaysLearning0 commented: thats great! :) +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You can use Qt. Do this in a terminal window:

$ sudo apt-get install libqtcore4 libqtgui4 libqt4-dev qt4-qmake qt4-doc qt4-demos qt4-assistant qt4-designer qtcreator qtcreator-doc

Some of the above might be redundant, but what the heck. And most of it is probably installed already as part of the distro or as dependency of other, already installed packages (since Qt is pretty wide-spread in Linux GUI world).

At that point, you should be able to make a project like this one:

#include <QApplication>
#include <QWidget>

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

    QWidget window;

    window.resize(250, 150);
    window.setWindowTitle("Simple example");
    window.show();

    return app.exec();
}

Save it to file "simple_example.cpp", go to that directory in a terminal, and run:

$ qmake -project
$ qmake
$ make
$ ./simple_example

If the above works, and it should (in the tradition of Linux being automatic and easy), then your setup is working, at least basically (you can browse synaptic for anything that starts with "libqt" for more plugins and add-ons, like opengl, sql, xml, svg, etc.). The above is just a simple example, the more usual approach is to design the GUI window using Qt Designer (by dragging and dropping GUI elements, instead of having to code everything in), save it to some .ui files, implement some event handlers (called "slots" in Qt), and create a qmake project file. It is a slightly more involved building process, but nothing to be afraid of.

There are plenty of tutorials on Qt. Like …

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

>>CB current version is 10.5 and is distributed with gcc version 4.4.1 copyright 2009. Is that not the same as current version of MinGW without CB?

The current release version of GCC is, of course, 4.6.1 (from June 27 2011). Of course, it takes a little while longer to get working on an archaic OS like Windows (with MinGW). So, the current version of GCC on MinGW's repository is 4.5.2 (released by GCC in december 2010, and ported to MinGW in january 2011). If you compile from source, you have 4.6.2 and 4.7.0 (experimental) available as well.


>>I suspect a bunch of parrots just jumped on the bandwagon.

I do admit that I am a parrot when it comes to DevC++. But I did, like many others here, see several threads that report bizarre problems, and after suggesting to upgrade for a more recent IDE/Compiler setup, problems were fixed.

If I recall, many of the problems people encounter with DevC++ have to do with using a recent version of Windows (Vista or 7) and getting problems with crashes at execution. This is the main problem with using an out-of-date setup, you risk that the run-time libraries, headers or ABIs will be no longer compatible with the OS it's running in or the libraries it is linking to (especially when using non-microsoft compilers and run-time libraries).

As far as DevC++ being good or bad, in the context of using it when it was up-to-date, …

ddanbe commented: Nice. +14
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The answer is:
- I don't know.
- Boost.Program-options
- Boost.Date-time

Let me elaborate:

For the first problem, "IsDebuggerPresent", it is the first time I hear of such a function, I have no idea if it has or can have an equivalent in Linux. As far as I know, you do either debug builds or release builds, so there is no need for a run-time check for a debugger being possibly present. I might be wrong.

For the second problem, "GetCommandLine", I would recommend you switch entirely to Boost.Program-options for both Linux and Windows. This is a cross-platform library that will allow you to create a global object that captures, parses, and holds all data from the command-line (as you specify the possible user-inputs and capture the command-line input at the start of main()). This will be better in either cases, windows or linux.

For the third problem, I would recommend you use Boost.Date-time. Again, this is a cross-platform library which is implemented such that it takes the most precise timer available on the current platform. Basically, you ask for local_time in microseconds or nanoseconds and you will get it to the best possible precision available. You should probably switch entirely to that library for both OSes also.

As a final note, when porting code between OSes, you definitely want to take an approach like that of Boost. This means, you should wrap all the OS-specific in compact …

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

Yeah, you are correct. You will usually not gain anything at the end by trying to force the padding to not be done (if there is a way to do so). Usually, it will be much less efficient.

If memory is really a problem, you might consider clustering several objects into one. As follows:

#include <iostream>

struct A {
  int x[sizeof(int)];
  char c[sizeof(int)];
};

int main() {
  std::cout << sizeof(A) / sizeof(int) << std::endl;
  return 0;
};

That way, each object of class A actually stores "sizeof(int)" number of records, and at the end, there won't be any padding because usually the sizeof(int) corresponds, on most systems to the alignment size. Then, to store the records, you can wrap a vector of objects of class A with a custom container that translates element access to sub-elements of the 'A' objects.

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

Visual C++ is an Integrated Development Environment (IDE) from Microsoft to program in C++. C++ is a programming language. There are many alternatives to Visual C++ as an IDE (and compiler). Visual C++ uses the microsoft compiler (MSVC for short). As of version 2010, the Microsoft compiler is pretty much a standard-compliant C++ compiler (I couldn't say as much of earlier versions), it does include some Microsoft-specific extensions, but I don't think they should be a concern to you at this point. The most notable alternative compilers are: GCC (GNU Compiler Collection) which is free and very standard compliant (with a few extensions as well); ICC (Intel Compiler Collection) which is expensive (few thousand dollars) but highly optimized; Comeau which is not free but cheap and it is the only compiler that is entirely and strictly compliant to the C++ standard (and it is mostly used to test if code is standard, not really for production code).

An IDE is essentially a glorified text editor for coding (and many programmers just use a text editor for coding, not a full-blown IDE). Alternative options include: Code.Blocks (free); Eclipse C++ (free); Visual Studio (not free, from Microsoft, is basically an enhanced version of Visual C++, the Express edition is free, with reduced capabilities); Qt Creator (free); and KDevelop (linux-only). Just to name a few. There are plenty of threads here and elsewhere that discuss the best choices.

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

The problem is this line:

return insert_comma_helper(
           integer.substr(0, size - 3),
           result = integer.substr(size - 3, 3) + ',' + result);

The reason why tail recursion is not done in this case is because you have temporary string variables in your recursive function call. That is the main difference between the two code snippets (the first only has integer temporaries). This makes a big difference because the std::string requires destruction, which will be executed just _after_ the return-statement, rendering tail-recursion impossible.

There are certainly ways in which you could allow tail-recursion in this case. The main idea is that all things that are not part of the parameter list or of primitive types should be already destructed (or not created yet) at the point of the return-statements. This can often be implemented using scopes and adding working variables as parameters to the function (which is OK most of the time since you usually write a recursive function as a local function (like you did) or some other form of "hidden" helper function, and thus, it doesn't affect the actual interface function that a user would call). With that in mind, I would think that this solution might have a much better chance of qualifying as a tail-recursion:

//here, I break const-correctness, but it does no harm since the function is
// local (the original "integer" can be copied by caller), and this gives 
// you a free string variable that doesn't ever get destructed in all recursions. …
m4ster_r0shi commented: very interesting, thanx +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Is this the Java forum? I'm confused... no, it is the C++ forum. Please post your code in the appropriate programming language for the forum!

Whatever Random is, I assume it is a class that you wrote or your prof gave you as part of the assignment, because it is not part of C++ standard libraries (I just wanted to point that out because there are many clues in your code that suggest you are a Java programmer). To generate random numbers in C++, you can use rand() (and srand() to seed it), or any random number generator for the <random> library (may not yet be supported by your compiler, it is from the upcoming C++ standard).

The "Fatal Error" is due to either the fact that most C/C++ compilers require an empty line at the end of the code (so you need to leave at least one empty line at the end), or it is due to the fact that you don't have a main() function. The main() function you have is a static member function. This is not C++ (it is Java). A main function in C/C++ is like so:

//free-function
int main() { //must return a value of type 'int'
  //insert code here..
  return 0; //return 0 if all went well, otherwise return an error-code of your choice.
}

//the other alternative is to capture the command-line arguments as well:
//int main(int argc, char** argv) {

Second, you shouldn't have a default constructor that …

NathanOliver commented: Very well done. To bad we can only add once :) +9
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I shall not fear any optimisation surprise?

Do not fear. You are 100% guaranteed that if you have two base pointers which are identical (same address), then they point to the same object. And when I say 100%, I don't mean 99.999%, I mean 100%.

What you might/could/should fear, depending on the complexity of your class hierarchy, is the opposite case. That is, if you use multiple inheritance and don't use also virtual inheritance, you could have the problem that two base pointers which are different actual point to the same object. Read this to know why.

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

>>does the C++ standard permits a C++ compiler/optimiser to use a sort of "copy on write" optimisation for the specific case I mentionned?

No. C++ implements value-semantics. This means that two different objects can never be two references to the same object. You can, of course, have two references or pointers to the same object, but that is entirely under your control, the compiler has little to do with that.

There are certain optimizations that the compilers are allowed to do when it comes to base versus derived class pointers. That is, if you hold a pointer to a base-class object, but the context makes it obvious to the compiler that the object is of a particular derived class, the compiler is allowed to by-pass the virtual function call and make an ordinary function call to the function it knows will be called anyways via the virtual dispatch mechanism. For example, a trivial case:

#include <iostream>

struct B {
  virtual void print() const = 0;
};

struct D : B {
  virtual void print() const { std::cout << "Hello World!" << std::endl; };
};

int main() {
  D d1;
  B* b1 = &d1;
  b1->print(); //here, the compiler will most likely by-pass the virtual table look-up because it is clear from the context that b1 actually points to an object of class 'D', and so, it can call D::print() directly.
  return 0;
};

You can try the above and output the assembly listing for it and you will …

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

>>How are the programs made so that they run with GUI interface and stuff like that?

GUIs are made through the use of external libraries (either OS APIs or other (cross-platform) GUI libraries).

Usually it is not really recommended to start making GUI applications until you have a pretty good grasp of OOP, since most GUI libraries are object-oriented and rely heavily on things like pointers, inheritance, polymorphism, abstract interfaces, event-driven software, etc. However most OS APIs and some simple GUI libraries use what is essentially a collection of C-style functions, but they are generally much harder to use (as in, it makes you write a lot of code, in a painful way).

Qt is a free GUI toolkit that is very good and cross-platform (but there are others like MFC, WinForm, wxWidget, VCL/CLX, etc.). I would recommend starting with Qt. If it turns out that it seems too complex, then maybe you will have to wait some more to get a more solid grounding in OOP and C++ (none of the other GUI tools will be any easier). Just follow online tutorials and start from there.

>>Are they exported differently

As for integrating console-program code into a GUI, it is mostly a matter of implementing the event-handlers (code that executes when the user does something, like clicking a button or menu). Implementing the event-handler is basically just normal C++ coding (include the headers you need, and code). The second difference is that …

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

>>I guess it has just monitored hundreds of thousands of games and returns the best statistically winning move (given the previous moves).

Not exactly. Such gross statistics are not good enough in general. As I said earlier, they typically do an online estimation of a Hidden Markov Model (HMM). The hidden state is representative of the "state of mind" of the player (usually modeled by some vector of numbers that is large enough to account for the complexity of the decisions involved). Then, the result of the previous game (the computer's move) will modify the state of mind of the player, and that next state of mind will determine (with some probability) the most likely next move. The job of the computer which is doing the learning is to try and determine the two relationships involved: the state transition function and the state-output function. In other words, the learning algorithm has to try, based on enough evidence, to estimate how his previous move causes a state transition in the human player's state of mind, and then has to estimate how a particular state of mind translates to probabilities of an output (next move by the player). Standard algorithms for this are typically classified as EM (Expectation Maximization) which is a kind of double-step algorithm (like predictor-corrector algorithms), the best and simplest example of which is the Viterby algorithm (which is a dynamic programming version of EM). The idea is usually to assume a …

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

>>but seeing as the decisions are totally random and winning is down to pure luck

@iamthwee: You are making the strong assumption that humans playing rock-paper-scissors are actually making random choices. That is demonstrably false. Humans are no better at generating random numbers than computers, in fact, they are much worse. Humans are not truly capable of coming up with a random pick, there is always an underlying logic or strategy (even in situations where a strategy is meaningless), we simply cannot "compute" the pick any other way. This is a well known fact, especially in the realm of mentalism (magic (or illusionism) based on mental tricks), for instance, if you ask a person for an arbitrary number between 1 and 100, you have about 40% chance that the number picked will be 37 because even if nothing makes one number more random than another, we, humans, in that situation, tend to not go for certain numbers that don't seem random enough to us (like all even numbers, all numbers below 20 or so, all the numbers that appear in multiplication tables we learned as a child, etc.), and the result by elimination and not going to far in the high numbers is 37. Similarly, many mentalists use "suggestion" which just means that they say a few innocent- and inconsequential-sounding things before they ask you to pick a card or make drawing, but that is enough to suggest to your mind to pick a particular logic that leads to …

iamthwee commented: nice +15
tux4life commented: Solid post. +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The math is very simple. Take the difference between two pair of points (like pt2 - pt1, and pt3 - pt1) to get two vectors, take the cross-product of the vectors, and normalize it. That's it. In other words:

void GenerateNormal(float x[3], float y[3], float z[3], float &ox, float &oy, float &oz)
{
    //get difference vectors:
    float dx1 = x[1] - x[0]; float dy1 = y[1] - y[0]; float dz1 = z[1] - z[0];
    float dx2 = x[2] - x[0]; float dy2 = y[2] - y[0]; float dz2 = z[2] - z[0];
    //cross-product:
    ox = dy1 * dz2 - dz1 * dy2;
    oy = dz1 * dx2 - dx1 * dz2;
    oz = dx1 * dy2 - dy1 * dx2;
    //normalize:
    float mag = sqrt( ox * ox + oy * oy + oz * oz );
    ox /= mag;
    oy /= mag;
    oz /= mag;
}
mrnutty commented: vedy vedy niceeee +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You are right. A typedef is nothing more than a new name for a type, in that sense, it is an alias. And, it really is just a new name for a type, not a new type in and of itself. It serves the purpose of shortening names to make the code more readable, and to associate types as nested in a class declaration (see STL containers for examples). Typedefs are especially useful in generic programming and template meta-programming, because the names of the types tend to get very long (with many template arguments). They are also useful in template meta-programming to declare the results of meta-functions. But still, typedefs are just an alias for a type. In fact, this is what they are now referred to as in the new C++ standard, as type aliases, with a new syntax:

typedef std::size_t size_type; //old syntax (still valid in C++11, of course)

using size_type = std::size_t; //new syntax.

template <typename T>
using vect_type = std::vector<T>; //new syntax allows template aliases too.
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The "natural word size" is the 32bit in "32bit architectures" or the 64bit in "64bit architectures". It is just the size of normal integral types which are used all over the place in a program (e.g. pointers and integers).

>>i still wish i knew why about odd address's and why they cause unaligned memory accesses

It's the other way around. Misaligned memory cause "odd" addresses. Normally, compilers will align the memory to avoid "odd" addresses (and by "odd", it is meant as a non-integral multiple of the natural word size of the architecture, of course, not the regular meaning of "odd numbers"). For example, consider this class:

class Foo {
  char c;
  short s;
  int i;
};

On a 32bit architecture, the int type will normally be of 4 bytes, the short type of 2 bytes and the char type of 1 byte. So, one could expect that the above class would take 7 bytes of memory. However, the compiler is allowed to take the architecture of the computer into account and decide to align the memory on 4 bytes intervals, leading to a total size for this class of 12 bytes (5 of which are not used). This will avoid any "odd" addressing, and will generally be more efficient. There are a few ways to force a compiler not to do this alignment, but these are complicated and should not be used unless you have a really good reason to do so. And some compilers won't …

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

I think you are asking the wrong question. Programming is a tool. Asking if people get bored of programming is like asking a plumber if he gets bored of using a wrench, he would probably tell you that his job is not about using a wrench but about helping people with their plumbing problems and that is what he is motivated and proud to do.

Of course, programming takes a lot more time to learn how to do well. So, during that time, it does require an eagerness to learn and general interest for programming. With that, I don't think it gets boring, unless you picked the wrong projects for you. It does get frustrating from time to time during the learning phase because nothing seem to work as you wish and you are constantly stumbling on bugs or problems that you don't know how to solve (yet). But the sooner you can start focusing on problems that you want to solve, the more motivation you have to fight through these difficulties, and if you love to solve tough problems, there are plenty of those in various applications of computer programming.

Of course, the "job" can get repetitive and boring for time to time, but what job isn't? You have to look at the bigger picture to remind yourself why you are going through this less exciting part (like refactoring a large piece of code).

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

You need to put those #include statements for winsock and win2bth into the .c file. This is because you are going to need to #include your header file into your MinGW project, which will drag along the bluetooth windows includes that are causing problems with GCC. You don't need those includes to create your header file, so just put them in the .c file.

Second, you need to declare your functions in your header file with the extern "C" as well (in fact, that's where it matters the most).

Third, you probably want to compile this as a small DLL, so you also need to declare those functions as exported/imported, as so:

#ifdef COMPILING_DLL_MODULE
#define DLLFUNCTION __declspec(dllexport)
#else
#define DLLFUNCTION __declspec(dllimport)
#endif

extern "C" int DLLFUNCTION CreateSocket();

So that when you compile the DLL, you set the #define COMPILING_DLL_MODULE, and when you use your DLL, you use the same header, but without defining COMPILING_DLL_MODULE (thus, causing the functions to be imported).

To know if your code is working, you should first use this code with a simple main() function to test that you can connect / read / write / close successfully. Do that test on MSVC without compiling this into a DLL, that will be easier for debugging if there are any trouble. Once you know that your code works, compile it as a DLL and import it to your MinGW project.

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

Well, obviously, your example is a straw-man, you would not want to upcast in that case.

One of the main points of Object-Oriented Programming is the concept of Polymorphism, which entirely relies on upcasting and virtual member functions. If you are not familiar with virtual functions, it is almost pointless to convince you of the purpose of upcasting. In your example, you could have:

class shape {
  public:
    virtual double getArea() const = 0; //virtual function to compute the area.
    virtual ~shape() { }; //don't forget to make the destructor virtual in the base class.
};

class rectangle : public shape {
  private:
    double width, length;
  public:
    virtual double getArea() const { return width * height; };
};

class circle : public shape {
  private:
    double radius;
  public:
    virtual double getArea() const { return 3.14159 * radius * radius; };
};

int main() {
  std::vector< shape* > v;
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  
  double totalArea = 0;
  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    totalArea += (*it)->getArea();
  std::cout << "total area of all shapes is " << totalArea << std::endl;

  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    delete *it;
  return 0;
};

The point in the above example is that the vector of shapes can hold any kind of shapes (rectangles, circles, what have you), and not care of what kind of class they are, because all that is needed is …

Aranarth commented: Good post, as always +7
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Narue's answer is good, of course. But on a less formal basis, I see encapsulation and abstraction as sort of two sides of the same coin. In both cases, you usually hide away the details that the user of your library or class doesn't need to know about (hiding data and/or implementation details (like helper functions)). In a sense, encapsulation is asking yourself: What are the things the user shouldn't see? and abstraction is asking yourself: What are the only things the user should see? Most software components have things the user really shouldn't see (e.g. see the PImpl idiom) and things that are part of the interface of this software component (see "programming by contract in OOP"). In an ideal world, the split is clear, in the real world, the line is blurred, so it makes sense to think of both sides of the question (should this thing be hidden? is this thing part of the (abstract) interface?).

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

>>what is a namespace

A namespace is literally a "name-space". When programming large libraries, you need names for everything (e.g. data-types, variables, constants, classes, functions, parameters, etc., etc.). How do you make sure that the names that you pick will not conflict (or "clash") with other names in other libraries that a programmer might be using at the same time as yours? The answer is: you put it in a namespace. A namespace creates a little private world (or space) where you can name things the way you want to without fear that it will clash with other names, because those other names will be in other namespaces. It is also a way to "hide" parts of your library by putting it in another sub-namespace that is not published (often that "hiden" namespace is called "detail", by convention). For example, if I wanted to make my own version of std::vector, but I didn't want it to be confused with std::vector, but still enjoy the nice and intuitive name "vector" for the class, I could do this as so:

namespace my_lib { //this puts all the stuff between { } into namespace 'my_lib'

template <typename T>
class vector {
  //....
};

};

//The user can now use both, without conflict:
int main() {
  std::vector<int> v1; //using the standard version
  my_lib::vector<int> v2; //using my library's version.
};

The statement "using namespace std;" or "using namespace my_lib;" means that you "import" all the names that are defined in the std namespace …

Ancient Dragon commented: great :) +17
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Generally, to be safe, you implement these kinds of "instance counters" wrapped in a factory function. Typically, you also don't want spurious copies and things to be created, so you make the class non-copyable. This way you count only the "uniquely new" objects that were created, not copies and temporaries. By making the class non-copyable, you force it to be used via a pointer, and the only function to create that pointer is your factory function, which records the instances created:

class People {
  private:
    int ssn;
    People(int aSSN) : ssn(aSSN) { }; //constructible only from factory Create().
    ~People() { }; //destructible only from factory Destroy().
    People(const People); //non-copyable.
    People& operator=(const People&); //non-assignable.
  public:
    static People* Create() {
      static int objectCount = 0;
      return new People( ++objectCount );
    };
    static void Destroy(People* p) { delete p; };
};

int main() {
  People p1 = People::Create();
  People::Destroy(p1);
  return 0;
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The sort algorithm (or the std::set container) have an optional parameter which is the Compare function for the elements to be sorted. This comparison function is, by default, the less-than operator which ends up sorting things in increasing order. You simply need to make a functor (callable object) which does the kind of comparison you need for your problem (or it can be a function-pointer, but a functor is more practical). Here is an example to sort by the X value:

struct CompareByX {
  template <typename PointType>
  bool operator()(const PointType& p1, const PointType& p2) const {
    return p1.getX() < p2.getX();
  };
};

int main() {
  std::vector<Point2D> v_2D;
  // fill v_2D with values...
  //then, sort according to X:
  std::sort(v_2D.begin(), v_2D.end(), CompareByX()); //create the CompareByX functor.

  //similarly for Point3D:
  std::vector<Point3D> v_3D;
  //..
  std::sort(v_3D.begin(), v_3D.end(), CompareByX()); //you can reuse the same functor since it is template-callable.

  //you can do pretty much the same thing with a std::set (which keeps it sorted all the time):
  std::set<Point2D, CompareByX> s_2D;
  //just fill s_2D with data, no need to sort afterwards since it is always in order.
};

Just make other functors for Y and DistFrOrigin, and you are done. You can also make those functors as either classes nested in the Point2D/Point3D classes, or as static member functions of Point2D/Point3D classes. Here is an example as a static member function in the Point2D class:

class Point2D {
  //... all your other stuff...
  public:
    static bool CompareX(const Point2D& p1, const Point2D& p2) {
      return p1.x …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@raptr_dflo: the setDistFrOrigin() is a private function that is called in the constructors and in every set() function of the Point2D class. So, the distance value that he gets is not garbage, he actually handled this problem quite well (making setDistFrOrigin() private and calling it at every modification of the data, to keep it consistent at all times). You seem to have missed the original problem, that is, how to print his Point2D class in two different ways (with and without the distance value after), and I provided two solutions to that problem.

You are right about pow() being inefficient here. I did point that out in the code I posted. For small, integer exponents, it is always more efficient to multiply the values out instead of making a call to pow().

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

The easiest solution is surely to use simple print() functions instead of overloads, as follows:

//in the header:
class Point2D {
  //...
    void print(ostream& out, bool WithDistFrOrigin = false) const;
};


//in the .cpp file:
void Point2D::print(ostream& out, bool WithDistFrOrigin) const {
  out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]";
  if(WithDistFrOrigin)
    out << setw(3) << "" << p2d.distFrOrigin << endl;
};

This way, if you just call "print" on your point (passing the output-stream), you will get the output without the distance from origin, but if you add a "true" value to the call, you will get the distance from origin output as well.

If you absolutely want to use the >> operator on your Point2D objects, then you need an additional little trick. Operator overloads are selected based on the type of the parameters (and the number of parameters is fixed, so you can't add a flag to do one or the other printing method). So, in order to select different printing methods, you have to change the type of your object, which is actually quite trivial to do with a simple nested class:

class Point2D
{
  protected:
    //Declarations
    int x;
    int y;
    double distFrOrigin;	
    //Function
    void setDistFrOrigin();

  public:
    //Constructor
    Point2D(int aX = 0,int aY = 0); //use default parameters instead of 2 constructors.

    //Set Methods
    void setX(int aX); //use parameter names in prototypes to be more descriptive. 
    void setY(int aY);

    //Get Methods
    //If a member function does not …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yes, you can do so. But, of course, not using "dynamic polymorphism" but "static polymorphism" (as in, at compile-time). In your example, you don't need dynamic polymorphism, so it will work (when you really do need it, it won't).

The basis for achieving this is via a clever technique called "TypeList", developed the all-mighty template wizard himself: Andrei Alexandrescu. I suggest you read his book if you are really serious about learning to manipulate templates (his book: "Modern C++").

In a nutshell, here is the typelist technique. You need to build a list of types, but, in template meta-programming, everything has to be recursive (which is not really a problem since everything is done at compile-time, it will just increase compilation-time). So, you can build a single-linked-list of types with the following simple templates:

struct null_type {
  typedef null_type tail; //cycling terminator.
};

template <typename T, typename Tail = null_type>
struct type_list {
  typedef T type;
  typedef Tail tail;
};

So, the above can be traversed recursively (as with a normal linked-list) until the tail type is the null_type . Now, if you need random-access, as with any linked-list, to mimic it, you have to traverse from the beginning up to the element of the index (but since it is done a compile-time, it doesn't really matter at the end, no run-time overhead). Of course, the index has to be known at compile-time. So, here is a simple type-list indexing template:

//general type indexer
template <typename …
L7Sqr commented: I'm reading his book now; great stuff. Great example here, too. +6
jonsca commented: Great examples!! +14
alwaysLearning0 commented: nice example. +4
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You have indeed a simple problem of terminology.

What you are describing is a classic problem in, at least, the fields of machine learning and data mining. The problem is called "data clustering" (which is part of the field of "unsupervised learning methods" for "data classification").

If you search for these terms, you will have much better luck, I guarantee.

As for the most suited algorithm for your simple problem of clustering simple integer numbers, it is definitely the "K-means clustering" algorithm. The algorithm is very simple:

1) Start with K random elements in your set as the starting means of your clusters,
2) Put all the other number together with whichever mean they are closest to
3) Then recompute the mean of each cluster,
4) and Repeat, until you have no more change in the clusters.

Very simple, guaranteed convergence. Although, there might be a more specialized algorithm (or version of it) for this 1D case (since K-means is more generally applicable to any dimensionality and any distance metric). And, of course, there are refinements to this basic algorithm (and entire fields of research are dedicated to this), but for your simple problem, this simple algorithm is definitely good enough, and can be implemented in a matter of minutes.

Jsplinter commented: lol, I thought so. Thanks for getting me on the right track! +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

D) Use Boost.Multi-Index. This is a library for keeping an array sorted according to multiple indices (i.e. keys). This is probably the best and easiest way to keep the list "sorted" according to both the key and the value at the same time.

However, if you just want to completely switch from one ordering (according to keys) to another ordering (according to values), then store them as a pair, and make two functors for the two kinds of comparison:

typedef std::pair<MyKey, MyValue> MyPair;

struct CompareByKey {
  bool operator() (const MyPair& a, const MyPair& b) const {
    return a.first < b.first;
  };
};
struct CompareByValue {
  bool operator() (const MyPair& a, const MyPair& b) const {
    return a.second < b.second;
  };
};

Then either you use std::vector and std::sort, or use two sets.

int main() {
  std::vector< MyPair > v;
  //... push all the elements into v.
  std::sort(v.begin(), v.end(), CompareByKey()); 
  //now you have a vector sorted by keys and can be accessed by binary_search.

  std::sort(v.begin(), v.end(), CompareByValue());
  //now you have the same vector but sorted by values.

  //with two sets:
  std::set< MyPair, CompareByKey> sk;
  //insert all the elements into sk and you have a sorted set according to key.

  std::multiset<MyPair, CompareByValue> sv;
  std::copy(sk.begin(), sk.end(), std::back_inserter(sv)); 
  //now you have another set with the values sorted by value.
 
};

You can also have a std::vector of the pairs, and then keep a std::set and a std::multiset that holds the indices into the vector, sorted (with similar kinds of functors) by …

Jsplinter commented: Once again, awesome post! +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

conio.h is a non-standard library for MS-DOS. You can read the little wiki on it.

The only function that requires conio.h in that piece of code is the final statement getch() whose sole purpose is to pause the program until you press a key.

First of all, you should definitely not remove the .h.

Second, if your compiler does not provide conio.h, then you need to remove that include and also remove the getch() statement. You can achieve almost the same effect by using cin.ignore(); cin.get(); (but it will require that you hit enter).

Finally, a little correction:
>>I know that this is old one and the .h format is replaced with using namespace
That is not true at all. Basically, only the standard libraries do not have the .h extension, and I don't really know why, maybe to distinguish them from everything else (and legacy versions of the standard libraries). Whether namespaces are used or not does not affect whether the .h extension is there or not. The compiler basically ignores the extensions or whatever, it treats the #include file as a filename that it looks up in its include search-directories (and C++ standard library headers are files without an extension). In C++, the common extensions for header files are .h and .hpp, and namespaces are used and should be used in all library code (standard or not). In C, only the .h extension is used and there are no namespaces. …

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

Ok, in your second last post, you are right! That is exactly how it goes.


As for 'theName', there are two of them. Both are inherited from Person, but one is inherited through Student and the other is inherited through Teacher. This is why you can access one via Student::theName and the other via Teacher::theName. The problem is if you try to access 'theName' directly (without the 'Student::' or 'Teacher::'), then the compiler will have a problem with that because there are two to choose from.

So, 'theName' is the same case as 'theClass' which you understood correctly. The only difference is that the two 'theName' variables (the one from Student and the one from Teacher) are initialized to the same value by passing the same string to both constructors of Student and Teacher (which each carry that string over to their base class 'Person').

At this point, it might seem odd to you that there are two 'theName' when there really only need to be one. But the compiler can't know that. There is a mechanism in C++ to tell the compiler that this is the case, and it is usually used in this kind of multiple inheritance case, and it is called virtual inheritance, you can read more on that here.

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

>>hoping <enter> would made an eof approach

Yeah, cin is special, it basically never has an end, because it can always wait for the user to input more stuff. But, in any case, that kind of while(some_stream >> value) loop is pretty usual for other "normal" streams (like file streams and string streams). However, in this case you have heterogeneous data, so a loop is generally inappropriate for that (it is appropriate when you have sequential and homogeneous data, like a sequence of numbers).


For the rest, I pretty much agree with Clinton Portis. In these cases, you are usually better off inputting whole lines into a string stream and then deal with what you got in there (it is easier for inspection of the content, validating it, etc.). Of course, as with your code, you CAN do it without, but that doesn't mean you should.

Another useful trick with string parsing is to flip between string-stream and string. You can use the string-stream for sequentially extracting (formatted) information. And you can switch to string to have random-access (to count words or commas, or whatever defines the 'validity' of your input).

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

Yes, definitely. C++ cannot allow you to overload operators for its built-in types or any array of them, that would be too easy to abuse and too dangerous, with no gain. You definitely need to wrap this in a class, and you should also want to do so, because defining such a 4x4 matrix definitely requires more than a simple typedef.

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

In order to be able to print using << with a custom type (class), you need to overload the << operator of the std::ostream class. And since you are using some class inheritance, it is probably advisable to use a virtual print() function for printing the content of your class (the most derived one). You could do the following:

// In the declaration of the Account class:
class Account  {
  //...
  public:
    virtual ~Account(); //never forget to make the base-class destructor virtual.

    virtual void print(std::ostream& out) const;
  //..
};

// Then, in account.cpp:

void Account::print(std::ostream& out) const {
  out << "Account: " << num << " Balance: " << bal << std::endl; //or whatever way you want it to look.
};

// Then, if you want a custom printing for Checking, add in declaration of Checking:

class Checking : public Account {
  //...
  public:
    void print(std::ostream& out) const; //this overrides the base-class implementation.
};

// Then, in checking.cpp:

void Checking::print(std::ostream& out) const {
  out << "Checking "; //add some customization.
  Account::print(out); //call the base-class version of print().
};

//finally, somewhere like in account.h or in main.cpp:
// overload the << operator for a Account object
std::ostream& operator <<(std::ostream& out, const Account& obj) {
  obj.print(out); //call the virtual print function.
};

// And then, in main(), you will need to dereference the pointer before using <<.
int main() {
  //...
  cout << *(checking[0]) << endl; //remember that C++ indices start from 0, not 1.
  cout << *(checking[1]) << endl;
  cout …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Typedefs are just aliases, they don't "create a new type". So, you have to overload the operator for the underlying type. You can also overload with the typedef, but that will just overload for the underlying type as well.

So, basically, the rule applies as for the underlying type. If the type is a type for which you cannot overload (e.g. built-in type) or should not overload (like an STL container), then it is not possible. And if the type already has an overload for it, then it will conflict with your typedef'd overload.

Find a better option. Wrap it is a new class. You could also provide, in that new class, an implicit conversion operator. This will allow all built-in operator overloads to act on the type if there is no specific overload that you provided for wrapper class. But this technique can have surprising or undesirable side-effects.

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

>>would their definition then usually occur outside of the class scope?
Not necessarily. Operators can be non-friend as well if access to private members is not necessary. They can be defined outside the class declaration if they seem too long to remain in the declaration. Often people use the friend keyword just so that the implementation can be put in the declaration (even if private member access is not needed), when the function is very small it is sometimes nicer to have it in the declaration. But this is all just a matter of taste (however, when it comes to class templates, it is usually more natural to have them in the class declaration).

The main idea here is that free-functions should be preferred to member functions for essentially all operators that allow them. This is because of overload resolution, function hiding, and other considerations. Just get in the habit of overloading operators as free-functions (friend or not, in-declaration or not).

Jsplinter commented: will do +2