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

>>i can say for sure that it will work with internet

That's pretty vague. Surely, for internet-related programming, C/C++ aren't good choices. Although I am of the opinion that no education in programming is complete without being at least functional in C++ programming (because it is so central to the entire programming world), I have to say that if you have a particular area of work in mind and if the central aspect of that area is "the internet" than C/C++ are not very likely to be the languages you will end up using in that area of work.

You have to understand that there are three main lines of programming work in "the internet". First, you can do "networking", like programming servers, routing algorithms, and similar programs which are generally running on some server (and some clients) and works "under-the-hood" to manage data transfers and synchronizations and so on. For these types of applications, be prepared to work in UNIX environments (or Linux, or Solaris), and the more likely candidate languages to learn are Perl and Python, with some basics in C and then some web-scripting languages. Second, you have "internet applications" in the sense of desktop applications that makes heavy use of some underlying internet (and often also a database) connection with a server. For these applications, languages like Java and C# are the ones you will be most comfortable with and are most likely to encounter in that line of work. Finally, you have "web …

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

There are a number of things happening here that make this test flawed.

Generally when people make performance arguments between static versus dynamic polymorphism (i.e. based on templates or based on virtual functions, respectively), the thing that makes all the difference is whether the mechanism is static or dynamic. So, any test to compare the two is void if you make it trivial enough that the compiler can easily resolve the dynamic case back into a static one. I'll explain.

When the polymorphism is realized at compile-time (statically) then there are several advantages, i.e., additional things the compiler can do to speed up the execution. Amongst those optimization opportunities are these main ones:
- Replace the function call by an inline expansion.
- Do more aggressive copy-elision for the parameters and return values.
- Arrange the compiled code in the object-file such that related functions (related by mutual calls) are close together, minimizing cache misses.
- Work in-place and without indirection with the "this" object in member functions (when that object is stack-based and the call is inlined).
- etc... there are more I'm sure, I'm no expert in optimization techniques.

All these optimizations are clearly only possible because the compiler has knowledge of both the call-site and the called function at compile-time (and because the function is often uniquely tailored (templated) to the specific call-site making it an obviously good candidate for inlining).

So, in order to compare code that …

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

>>Is it possible to write a c++ compiler in c++ ?

Well, the steering committee of GCC believe so. I don't know of any compiler that is entire written in C++, but it is certainly possible. The only problem is that compilers need to be rock solid, meaning that you cannot just throw away decades of robust C code just to satisfy some C++ zealots. But, some compiler writers like GCC are now allowing C++ code to be added to the existing C code, and I think there is also talk of creating a separate development branch to port the whole thing to C++ (at least, make all the C code compliant to C++98, as opposed to ANSI C). Other than that, I would imagine some compiler vendors use C++ at least for some parts of their compiler's code (e.g. the front-end), but I don't know of any that is known to be entirely in C++, and that really doesn't matter much.

>>Its bootstrapping, right ??

Sort of. You can already boot-strap GCC. When I compile the latest GCC version from source (which I do every month or so), I compile it with the GCC compiler I already have. The build script that GCC uses will compile then entire code of the C compiler 3 times: first with any C compiler already installed on the computer, then once with the newly compiled GCC C compiler, and then again with the newest compiled GCC C compiler. …

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

>>However, I guess I don't understand why the object that was getting passed was const?

My guess is that the STL implementation of std::sort wraps the "compare" object inside another functor that takes either const-references or const-iterators. So, the only viable options when defining a comparison functor is to use either const-reference or value parameters, which makes sense from a const-correctness point-of-view, a comparison function should not modify its operands. STL uses const-ness pro-actively in these situations, I suggest you do the same.

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

The main problem, of course, with the code you posted is that the indirect_iterator class implements the assignment operator in terms of an assignment operation on the pointees, not the pointers. Because indirect_iterator was made with the assumption that it should behave exactly as if the iterator was an ordinary iterator in a container of values (not pointers), it has to implement assignment with deep copies. Evidently, if your pointees are const objects, then you cannot do any operation that would require the iterator's value-type to be non-const.

What you would need is a sort of hybrid indirect-iterator that would dereference the pointers for all "value-access" operations, and that would move the smart-pointers around whenever doing move / copy / assignment operations. The problem is that these are not distinguishable because they both go through the same operator, the dereference operator on the indirect_iterator class. For instance, the standard sort algorithm is most likely based on a swap operation like swap(*it1, *it2) which is a data-move operator that relies on the dereference operator of the iterator, then, it probably also calls compare(*it1, *it2) which is a data-access operation, but from the point-of-view of the implementer of the iterator class, these two operations cannot be distinguished at all.

The only way to solve this is to use an indirect compare operation and a normal iterator (to the pointers) for the sort operation. For other operations in which you want to have an indirect-iterator, just use make_indirect_iterator from outside your …

daviddoria commented: Thanks for the thorough analysis. +12
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you make functions that are re-entrant (or almost pure-functional) then you don't have to worry about anything. The main characteristic of a re-entrant function is that it has no dependence whatsoever on data from outside the function (excluding the input variables of course, and read-only access to global (quasi-)constants), and has no side-effects (it generates some outputs from the given input variables, and that's it, it doesn't modify any global variables or anything of the sort). In this case, once the function is provided with its input variables, it can, by definition, operate from start to finish without affecting anything else in the application or without being affected by any changes in the application's state. This implies that you don't have to worry one bit about using this function in a multi-threaded environment.

The fact that two or more threads are executing the same function at the same time makes no difference, each thread has its own execution stack for the function, and thus, each execution is entirely separate from one another.

What you have to worry about is SHARED DATA.

This innocent-looking function that caches the fibonacci sequence is a typical example of a hidden side-effect:

int GetFibonacciNumber(int i) {
  static std::vector<int> seq{1,1};
  while(seq.size() < i)
    seq.push_back(*(seq.rbegin()) + *(++seq.rbegin()));
  return seq[i];
};

Here, the fibonacci sequence is being cached in a static vector which is unique for all instances of the function and is thus a data element that is shared between threads that …

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

I'm not an expert with boost.spirit, but I don't think that it makes much sense to specify a delimiter which has "any number of spaces" as in the delimiter generator expression (*(karma::space) << ',' << *(karma::space)) . This is likely to be the explanation for the infinite loop (probably the star (or "any number of") isn't meant to ever be used in a generator expression, but compiles nonetheless and causes an infinite loop if used as a generator). So, I would replace it with either (karma::space << ',') or (',' << karma::space) (or with two spaces).

From the examples on the boost.spirit webpage it also seems that the generator expression given to the "generate_delimited" function should be one that has an "any number of" type format over the attribute to be outputted. In other words, it seems that the expected behaviour of your code would be to output only the first number in the sequence, and that this generator would be worth a try in case it is so:

karma::generate_delimited( inserter, '(' << karma::int_ << ')' << *('(' << karma::int_ << ')'), (karma::space << ',' << karma::space), r);
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

So, there is only a very trivial difference between a struct and a class . And struct was kept for backward compatibility with C, while class was introduced because it is generally more appropriate for Object-Oriented Programming purely on the basis of vocabulary (i.e. in OOP with about "classes" of objects) and on the grounds of default access rights and inheritance (private) which is more in-line with OOP design philosophy. But, in practical terms, the difference between struct and class remains trivial.

What you call "structures" is what experienced programmers colloquially refer to as "POD-types" (Plain-Old-Data types). These are basically simple little bundle of data like:

struct Vector2d {
  double x;
  double y;
};

By convention, in C++, people use the keyword struct when creating such simple classes, and thus, people sometimes call them "structures", but I tend to dislike this awkward, overly general wording.

So, the purpose of POD-types is similar to that of any other class, except that, in this case, you don't have any functionality to associate directly to the class (or very little functionality). In other words, when you just want to bundle a bunch of data elements together, not much more. POD-types are a special kind of "value-objects" (or value-classes).


>>How do they help with coding?

Well POD-types help with coding just because data structures are omni-present in programming tasks and very often all you need is to group a number of variables together as one logical entity, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster
#include <iostream>

int main() {
  for(int i = 0; i < 3; ++i)
    std::cout << "Ho! ";
  return 0;
};
Clinton Portis commented: lol +10
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You should remove the Shape:: in front of each function name within the declaration of the Circle or Triangle classes, you don't need that and should have it there (and that's the error your compiler reports).

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

>> Would the last line work?

No.

>> Or do I have to declare a vareable to do any math/calculations?

Yes, you can do computations to obtain the initialization value of a global variable, but you cannot do general statements.

>> Does it execute in a top down fashion?

Yes, but not really, at least, you shouldn't depend on it, it could be a subtle way to crash your program. Read this.

>> Or would I have to declare a function to execute that last line?

Yes and no. If you do as Narue suggested, then you don't need a function to execute that code at the initialization of sasd. However, any other more general set of statements (e.g. an algorithm of some kind) would require a function. But note that this function can be called in order to initialize one of the global variables, for example, you can do:

int var = 6;
int exponent = 4;

inline
int compute_var_exponent() {
  int result = 1;
  for(int i = 0; i < exponent; ++i)
    result *= var;
  return result;
};

int var_pow = compute_var_exponent();

On a final note, global variables are not recommended for anything beyond a simple test program, and experts generally only make use of them in very specific cases (often implemented as a Singleton). One of the reason they are generally undesirable is that they introduce a global state to the program which is hard to predict …

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

If you use the clock() function, it will return the clock ticks elapsed by your process only. My guess is that you have been using a general local-time function like "time()" to measure your elapsed times. The time() function and the clock() function are fundamentally different in the sense that clock() return the number of clock-ticks since the start of the calling process and only the clock-ticks consumed by the calling process are counted. In other words, if you use the clock function, there should be no variability introduced by having other processes running on the computer.

N.B. When measuring performance of algorithms that do file I/O, always expect variability just from the fact that file I/O is usually the main bottleneck operation and it is not very steady.

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

Well. Maybe WaltP has 1 in 50 chance of finding the error, but I have an eagle eye and a compiler built into my brain, which means I have a 100% chance of finding the error. And the error is at this line in your loop:

sum1++=p;

You have one too many + signs. The above line translates into:

sum1++ = p;

Which means that the variable sum1 is incremented by 1 and then, its old value is returned as a temporary value (formally, an "rvalue") which you then attempt to assign a value too (the value of p). Because of the nature of an rvalue (a temporary value) there is no way that you can assign another value to it, i.e., you can only assign a value to a non-temporary variable (formally, an "lvalue"). And thus, you get a compilation error like "lvalue required on the left side of the assignment".

I believe you meant to write:

sum1 += p;
WaltP commented: Good for you. Although my mini-teaching-session is now for naught. There's actually a reason I posted as I did. +17
PrimePackster commented: Thanks Man, You saved my day +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> I've been Programming in C++ for a year. I am done with Basics and all other OOP concepts(like inheritance,polymorphism and STL)

That's funny. I've probably said that (i.e. "I am done with ... ") every year since I started programming (13 years ago or so), but it was always preceded with "Last year as was such a noob, but now I am done with ...". The C++ learning curve is an endless recursion of "last year I sucked, now I'm awesome".


>> I want to be a game programmer, but i don't know what to study now?

Game programming is a huge topic in its own right. You should probably figure out more specifically what interests you.

As a starter, you should just start trying to render some basic stuff in 3D and move on from there. Either learn to use OpenGL, or take a head-start and grab an off-the-shelf rendering engine like Ogre3D. Later, you can figure out what is more interesting to you (e.g. rendering effects, particle systems, physic realism engines, game logic, animation (skinning), artificial intelligence, etc.). As soon as you are a bit comfortable with rendering basic stuff, then you can start thinking about some good idea for a computer game (of manageable complexity). That should keep you busy for a few years (it did for me).


>> Should I go for OpenGL or DirectX or GUI libraries or maybe something else.

awesome_cool commented: Thanks mike +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>What is the point of a static method?

The point of a static method is that it can access all the private members of the class but isn't tied to an object (instance of the class). I would agree that it isn't the most useful thing in the world. One typical use is the factory function pattern:

class Foo {
  private:
    Foo();  //private constructor.
  public:
    static Foo* Create() {
      return new Foo();  //can access the private constructor.
    };
};

The above idiom is useful if you want to enforce a certain means of creating the objects of a class, or if you want to inject some post-construction code, or furthermore, this idiom can be used to give names to the different constructors (e.g. "FromString()"). This factory function idiom is very wide-spread, and the syntax resulting from using a static function is very neat too, e.g., Foo* pobj = Foo::Create(); (but note also that "factory patterns" can refer to many variations that may or may not involve a static function). The singleton design pattern is another idiom that usually involves a static method for the same reason as above, to make the constructor private.

Another general purpose for static functions is to provide functions that are related to the class but don't need to manipulate an object of that class. However, do not confuse static methods with friend functions, which are typically more useful than static methods to add related functionality to a class.

Static functions also …

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

It works anywhere, but it _should_ not be used in a header file. The motivation is essentially that you don't want it to have repercussions on the code that includes that header file (i.e. the user of the header file might not want to import the std namespace, so you should never do it in a header file). So, the guideline is that if you want to use "using namespace std;" in your code, you have to restrict it only to cpp files, and thus, in the header files, you have to use the full qualifications like "std::string" or "std::cout".

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

First, the obvious, in both cases, you have compiled code, so it is all a matter of linking and loading.

In all cases, a .lib file is a static-link library, meaning that it is used by the linker to complete all the function calls that exist in your application that refer to functions in that library. At the end, the linker grabs all the compiled code from the library (only the functions that are actually called at some point) plus all the compiled code from your program, and bundles everything into an executable file. So, we call it statically linked because all the links between function call-sites and the blocks of compiled code for those functions are accomplished before the final executable is created.

Now, when you actually run an executable, the operating system has to do a number of things, of which I won't mention too many details. Basically, the OS has to "load" the executable, giving it a chunk of memory to work with and a virtual address space to address that memory. Then, the executable itself runs a certain amount of code to initialize itself as well, and then the "main" function starts executing.

In many ways, a DLL is conceptually more closely related to an executable than it is to static library. A DLL, like an executable, has to be loaded by the operating system which gives it a place to live in the system's memory, and allows it to run some initialization …

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

Well, facebook is a social network, which has the word network in it, which usually implies a graph structure. And, coincidently enough, facebook uses a graph structure at its core, how surprising... I didn't need to look far to find that out, look at the wiki or the developers' page.

Awais Ali commented: 2 +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>like make those unproper inline function become non-inline

Inline functions are not a problem. In general, small functions should be inline (e.g. set/get functions, empty constructors, etc.). Inlining is a very important optimization, and non-inlining just for the benefit of not having any function definitions inside a class declaration is an unnecessary pessimization of the code. Just thought I would point that out.


I agree totally with your "rant" on commenting the code. The habit of writing comments on the interfaces of code (i.e. in doxygen style) is one of the top qualities I consider a programmer can have.

I find that one good way to motivate people to use documentation is to generate a doxygen documentation from the code, with the option to "hide undocumented members". Then build a culture of referring to that doxygen document (usually nightly built on the source code server) instead of digging through the actual source code when looking for functions to use and stuff. This way, developers are strongly encouraged to document their "usable" code well such that others can find it in the documentation instead of always coming to him/her with questions or misusing his/her code.


>>Don't act different else you will become a jerk

This is not a problem of what you do, it is a problem of how you do it. You shouldn't position yourself as the "guy who knows better" or the "evil code scrutinizer" or whatever. Be humble. Just …

NicAx64 commented: because I can't get back to evil school , I decided to keep my job, so I ignore the pain and pratice to enjoy reading others crypt code. Ture , always become liberal will made others liberal to you. +7
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Ok. Now that you are almost there, I'll complete it.

Basically, the first two lines in your loop are almost correct. The other two lines should be taken out. This would give you this loop:

//Statement
  while(n > 0)
  {
    sum += n % 10; //notice '+=' here, which adds 'n % 10' to 'sum'.
    n = n / 10;
  }
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Because, in the first example, the use of inner2 is only within the definition of the function f() of inner1, while in the second example, the use of the inner2 class is in the declaration of the inner1 class. It is important to understand the difference here. Think of it as a two-pass process. In order for the compiler to build up a complete understanding of what a particular class is, it has to know its entire declaration (i.e. to be able to register what data members it has, what member functions it has, what nested classes / typedefs it has, etc.). But, when you define some functions inside the class declaration, in order for the compiler to know and understand fully the type of the "this" pointer for a member function for example, it has to parse the entire declaration first, and then parse the function definitions, even if they appear in the class declaration. In other words, the compiler looks at all the data members and member function prototypes first, and then comes back to look at the definitions of the member functions. So, in your first example, by the time the compiler looks at the implementation of the f() function, it has already a complete knowledge of the declaration of the inner2 class. With the second example, as the compiler tries to understand the prototype for the constructor of inner1, it finds a class that it has not yet seen, i.e. the inner2 class.

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

Before I say anything else, I must point out a few disturbing things.

First, this line:

__glModelReferenceClass__& operator(int index){return __glModelReferenceClass__(win,index);}

Should have been flagged with a compilation warning (if not, increase the warning level to the maximum, as you always should). This function returns a non-const reference to a temporary object. You shouldn't do this, it has undefined behavior, and even if it works, it doesn't mean it's OK to do it. Moreover, there is no need for a reference here, just return it by value (generally proxy-classes should be passed around by value because they are semantically just wrappers for a pointer, a reference, an index-container pair, etc.). Just do this:

__glModelReferenceClass__ operator(int index){return __glModelReferenceClass__(win,index);}

Second, you use the double underscore naming convention quite a lot. I don't know where you picked that up, it is not only illegal (at least for global identifiers as you have there) because names with leading underscores are reserved for the compiler-vendors, but it is also horrible readability-wise. If you want to distinguish your class names from other class names (like glWindow, not interfering other possible glWindow names) then use a namespace, that's what they're for, and you should use a namespace to encompass your code.

Third, when it comes to operator overloading, you should not overload operators in a way that breaks the semantics of the operator. An addition operator is supposed to perform an addition, not an insersion or concatenation or whatever your += operators are doing. …

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

>>Sooner or later someone will write: const char * pchar=text, where text is an instance of my text_class. Then later, text could independantly be relocated during an insertion of characters, and pchar will points to nowhere and disaster sooner or later.

Well sooner or later that "someone" will have to learn to program correctly and not do such a dumb thing. Do like the standard library does, specify that the char pointer provided by your text_class will not be valid after any subsequent use of the text_class object. Better yet, use the std::string class instead of your own version of it.

>>is there a way to permit only a conversion to a temporary variable

No, not that I know of. If you cannot control the destination type (e.g. it has to be "const char*" and not some proxy class), then you cannot detect whether it is going to be temporary or not, or enforce any requirement for it to be temporary.

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

VC10 supports some of the basic language features such as rvalue-refs. VC11 will add a few insignificant language features, but at least, in VC11, the C++11 standard library will be pretty much complete (put aside the things that cannot be implemented with the limited C++11 language feature support). But almost all interesting features will still be lacking at least until VC12, like variadic templates, template aliases, delegating ctors, inherited ctors, default/delete functions, and initializer lists.

I share your skepticism of MSVC's ability to every reach a reasonable compliance, given their track-record on delivering support for C++98, with about a 10 year delay (since MSVC2008 is about the first decent compiler they produced in that respect). But I think that most features of C++11 should be reasonably easy to add, at least, the GCC team managed to get more of them done pretty quickly, just lacking a few things.

So, I know C++11 is still theoretical for most, but I think it's good to start showing C++11 code (and how it solves some problems pretty neatly) just to build enthusiasm and make the switch as swift as possible (with more pressure on compiler-vendors).

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

I don't see much purpose for it. Stack-based objects are so much nicer to use than heap-allocated objects. I'd be curious to know about your use-case?

The solution is to use a factory function and private constructors, as suggested by firstPerson (and, of course, smart-pointers are strongly preferred to raw-pointers).

If you have C++11 support, there is a very nice idiom to create a factory function, as so:

class MyRational {
  private:
    int num;
    int denom;
    
    MyRational(int aNum = 0, int aDenom = 1) : num(aNum), denom(aDenom) { };
  public:
    //..
    MyRational(const MyRational&) = delete;
    MyRational(MyRational&&) = delete;
    MyRational& operator=(const MyRational&) = delete;
    MyRational& operator=(MyRational&&) = delete;

    template <typename... Args>
    static std::unique_ptr<MyRational>&& Create(Args&&... args) {
      return std::unique_ptr<MyRational>(new MyRational(std::forward<Args>(args)...));
    };
};

int main() {

  std::unique_ptr<MyRational> r1 = MyRational::Create(2);
  std::unique_ptr<MyRational> r2 = MyRational::Create(1,2);

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

>>I just think VLA should be implemented for backward compatibility with C code.

I think that the standard committee has been less and less preoccupied with backward compatibility with C. I think the C support rational can be summarized as: "if new C++ features can be realized without breaking C features, they will, but if C features have to be broken (or left unsupported) in order to implement 'superior' C++ features, they will be broken". The introduction of the "class" keyword instead of "struct" (which are essentially similar in C++) to not interfere with the definition of "struct" in C is a good example of the former, while the "auto" keyword in C++11 is a good example of the latter.

I know that some people like to think that C++ should be strive to be a super-set of C. It was the main opinion in the 80s. Now, there isn't as much motivation to do so, because very few people still see C++ as a super-set of C, and if anything, they see the backward compatibility for C provided by C++ as a low priority. Since C is also moving further away from C++ in its own way (VLAs, built-in complex numbers, and upcoming C1x features), I think it is time for you and many others to accept the divorce of C and C++.


>>It will be used only by complete beginners, and C code

I would teach beginners to use std::vector (and I …

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

Scott Meyers started a huge discussion on usenet about this topic, pretty much all the arguments you can think of there find you will.

The gist of the argumentation is that there are too few use-cases and the changes required to implement them in C++ are pretty big and deep. Basically, people argue that: 1) if you don't have a reasonable upper-bound for the size of the VLA, then you should use a dynamic array (on heap) or an STL container (like std::vector); 2) if you have a reasonable upper-bound, then you could simply use a static array with that upper-bound size and simply use a subset of it (e.g. have an STL-like container whose storage is a static array of fixed maximum size). And thus, the compelling use-cases are few and far between.

Then, you have to consider that even though C and C++ share many similarities, the type system is fundamentally different. C++ enforces stricter rules on types (i.e. it is more strongly typed than C). C++ also has a lot more compile-time mechanism, like sizeof , decltype , alignof , etc., whose behaviour would be deeply affected by the presence of one type whose true identity and size are not known at compile-time (currently, in C++, all types are resolved at compile-time, and many features depend on that). I'm not a good enough expert to really know all the changes that VLAs would trigger, but I know they would be significant and far …

sergent commented: . +7
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here are a few comments:

By convention, the type for all array sizes (and return value of sizeof()) is the standard size type, which is std::size_t . So, you should probably have:

template < typename T, std::size_t elements >

Your data member that you call "ptr" is a static array, not a pointer (as its name implies). It is important to understand that.

Since you are writing what is essentially a header file, you should NOT have an using namespace std; statement. This is an important guideline and you should learn to obey it sooner rather than later.

Personally, I don't like the use of the bare class template name within the class declaration (and worse, in the definition, if the compiler allows it). What I mean is this in the class declaration:

template<typename T,int elements>
class Array
{
 // ..
   const Array &operator=( const Array & );  //I don't like to see this.
  
   const Array<T,elements>& operator=( const Array<T,elements>& ); // I prefer this.

   //or, even better, this:
   typedef Array<T,elements> self;
   const self& operator=( const self& );

 // ..

When you move outside the class declaration (to write your member function definitions) you should always use the fully specialized name Array<T,elements> instead of the bare template name Array . That probably explains your problem with the assignment operator.

Now, for your first question about the iostream operators. This is a bit of mind-bending problem, that is, if you wish to understand the problem, as …

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

The basic requirement for the default assignment operator to be available for a class is that all the data members and base classes also have an assignment operator available (with the additional exception that data members of reference type also disable the default assignment operator because of the special semantics they have).

So, you can consider, for practical purposes, that the default assignment operator has the following implementation generated by the compiler:

class A : public B, public C {
  private:
    int x;
    double y;
    some_class z;
  public:

    //The default assignment operator would look like this:
    A& operator=(const A& rhs) {
      //first, assign base-classes:
      B::operator=(rhs);
      C::operator=(rhs);
      // then, assign the data members:
      x = rhs.x;
      y = rhs.y;
      z = rhs.z;
    };
};

Clearly, the above can only work if all the data members can be assigned a value, and if all base-classes have an assignment operator (default or not).

In your example code, the class A has a const data member which cannot be assigned a value (it is "constant") after initialization (in the initialization list of the constructor). So, the class A does not have a default assignment operator generated for it, and in turn, the class CMyClass will not have a default assignment operator generated for it either since it has a data member which is not assignable (m_A).

Jsplinter commented: Thorough. I see now. Thank you. +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>What did it mean before it was used for a variable? auto is a storage specifier in C (and kept in C++98). However, it is the default storage class for all variables in C/C++, which makes it a pretty meaningless specifier (i.e. it literally has no effect at all). A storage specifier is used to tell the compiler how long a variable should exist and where it should be stored or found.

Personally, I have never seen auto used anywhere (after 13 years or so), I had to look it up to answer your question because I wasn't even aware it was a storage class in C++ (I thought that only static , mutable and extern existed, which are the only ones that actually matter). Now, that I know about it, I am not surprised that I had never seen it before because it is clearly useless, i.e., it changes absolutely nothing.

In the C++98 standard, the storage specifiers auto and register are allowed because they exist in C and were kept for backward compatibility, however, they were essentially meaningless in C++98. The register specifier has a theoretical but small effect, but it will be ignored by almost all modern compilers (it's basically a hint to help the compiler to optimize code, but modern compilers don't need such a hint anymore). Today, the new standard (C++11) still allows the register specifier, but the allowance for the auto keyword to appear as a storage specifier was removed (e.g. a …

Zssffssz commented: Did more than expected (in a good way) +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Exporting a class is something that is pretty hard to do correctly. I don't recommend you try it. In general, I have not seen anyone do it on Windows (in *nix systems it's a different story). Generally, the idea is to export a factory function (and the corresponding destroying function) to handle the create/destroy of the object, and then make all member functions 'virtual' such that you get all the member functions exported for free. But, even when doing that, you still need to worry about a lot of ABI issues (ABI: Application Binary Interface). This is not an easy task (it literally took me 3 years to figure it out for my own purposes, as a little side project, of course).

Read this article, it's a pretty good start to understanding the issues involved.

The easiest solution, really, is to use only a C-style interface for your DLL. With that, your code could look like this:

In the test.h for both the DLL and the application:

#ifdef WIN32
  #ifdef COMPILING_THE_LIBRARY
    #define DLLFUNCTION __declspec(dllexport) __stdcall
  #else
    #define DLLFUNCTION __declspec(dllimport) __stdcall
  #endif
#else  //for *nix systems (no need for anything special)
  #define DLLFUNCTION
#endif

class test; //forward-declaration.

extern "C" {

test* DLLFUNCTION CreateTest(int aA);

void DLLFUNCTION DestroyTest(test* t);

int DLLFUNCTION TestNum(Test* t);

};

In the test.cpp for the DLL:

#include "test.h"

class test
{
  private:
    int a;
  public:
    test(int a);
    int num();
};

test::test(int aA) : a(aA) { }

int test::num()
{
  return a; …
Stefano Mtangoo commented: this is good one! +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> So in the end, there isn't any C++ features for what I want?

That I know of, there is no specific C++ language feature to allow this.

>> Are you aware of any discussions for future enhancement (such as the "scoped friends" suggestion above)?

I doubt it. The friendship relation is a very frowned upon feature. The expert rarely use it much (I know I don't), and generally say that requiring a friendship relation is an indication of poor design (I know I do). Generally, for standard committee efforts at improving the language, they rarely discuss of ways to make it easier to do the wrong thing, but rather concentrate on easier ways to do the right thing (for examples: rvalue-refs, explicit defaulting/deleting member functions, or the, now abandoned but really awesome, feature of "Concepts").

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

>>Believe it or not, there are programs out there that cost thousands of dollars and all they do is analyze beams.

Yes I know, and I've used them (PATRAN/NASTRAN, ANSYS, etc.). But lately I've been using one that is free and fairly feature-rich (thermo-mech, dynamic, multi-physics, etc.). This tool is called Code-Aster (for FEA) and Salomé (for the GUI). This is an open-source project with many university research partners and some industrial partners. I highly recommend that you use that as a basis for your project.


>>so let me explain a bit (in case you are not familiar with it) I am sorry but I think I have to explain it to you so you can help me.

I am quite familiar with the type of software you are describing. I'm not an expert in it (my field is more about multi-body dynamics simulation) but I do have a very good idea of what it entails (and I have studied, written and used finite-elements software before).


>>A simple programs would have several tabs, one for project information, another to indicate the beam information (basically a thick line) here you indicate how many spans and the type of support (fixed, pinned, etc…) another tab for the loading (you have to specify the coordinates, just the x and y cause 2d) and one to calculate and show results.

What you are describing is a GUI (Graphical User Interface) for a FEA / structural …

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

>>I can't for the life of me figure out a way to copy the value stored in the char array into a bigint and I don't think the developers of the bigint libraries intended for them to be used that way.

The developer of bigint did indeed provide a function for input/output with standard streams (istream ostream) and you can easily use that to turn a char-array into a bigint and vice versa, using the std::stringstream class. See the BigIntegerUtils.hh file.

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

This piece of code makes no sense:

struct NArcher {
  extern int enemyattack = 10;
  extern int enemyhealth = 20;
  extern int enemydefense = 5;
  extern char enemy = 'Nathan Archer';
} ;

First with the obvious, if "enemy" is supposed to store a string, it should be a string, not a char. You can either have char* enemy = "Nathan Archer"; or std::string enemy = "Nathan Archer"; (notice the double quotes for defining a string, the single quote is only for defining a single character).

Now for the more important problem, i.e., your use of the extern keyword. First, you have to understand the fundamental difference between a data member, a static data member and a global variable. A data member, like "foo" in:

struct myClass {
  int foo;
};

is a variable that is within an object of the class (myClass). This means that when you create an object of that class, e.g. myClass myObj; , you can access the data member inside the object with myObj.foo . This means that you have one such data member inside each object (each with its own value).

A static data member, as "bar" in:

struct myClass2 {
  static int bar;
};

is essentially a global variable that is associated to the class it is declared in. This means that there is one such variable in the whole program, regardless of how many objects of that class you have (or none). So, since a static data …

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

You forgot the "extern "C"" part. This is important because the C++ compiler mangles the names of functions (to be able to attach to the function name certain information required in C++, such as the types and number of the parameters the function takes). In C, there is no need for that (function's in C are not type-safe nor overloadable). So, when you ask to get the address of the function named "PluginEntry", the loader will not find it because the C++ compiler that generated your DLL will actually have changed that name to something else (e.g. "__XFS34W!PluginEntry34ZX@24!" or something resembling that). So, in order to tell the C++ compiler not to mangle the name of the function (and use "C" rules for external symbols), you add:

#include <windows.h>

extern "C" __declspec(dllexport) void __stdcall PluginEntry()
{
	MessageBoxA(0, "Plugin entry point!", "", 0);
}

Also, make sure that your PluginEntry function-pointer type is declared with the same calling-convention (stdcall) as:

typedef void __stdcall (*PluginEntry)();
jammmie999 commented: Thanks for professional, accurate, quick and easy to understand feedback! +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

A few things to check:

1) Verify that your library is correctly loaded, i.e. Test != NULL 2) Verify that your function pointer is correctly obtained, i.e. Entry != NULL 3) Make sure that the "PluginEntry" function (in your DLL) is declared with extern "C" 4) Verify that your calling conventions match for both the declaration of the "PluginEntry" function (in your DLL) and for the function pointer type PluginEntry.

Post your code for the DLL function and the definition of the function pointer type PluginEntry if you are unsure how to test the last two points above, we can tell you if it is correct or not.

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

Definitely GCC is the best (and only) compiler right now that has a pretty good support for C++0x (C++11) features. A quick look at this table reveals this pretty clearly. And specifically for GCC here. From looking at the list, you can see that 4.6 is a pretty good version, the things added by the absolute newest version (4.7) are not that important (and, of course, 4.7 is not released yet, but under development, so it can be hard to get it working on Windows). As suggested, you can use the nuwen build of MinGW for the state-of-the-art releases of GCC for windows. Using Cygwin is also an option I guess.

As for MSVC, don't even think about any version before 2010. Also note that, unlike GCC, MSVC enables C++0x features by default (in GCC you have to use the option -std=c++0x , or -std=gnu++0x for the GNU dialect). I wouldn't put too much hope in MSVC for standard compliance (considering the MSVC 2008 is the first decent version with respect to the C++98 standard), although this post is encouraging.

Another important consideration is the standard library support. On GCC, it is pretty close to complete (except for the things that rely on unsupported language features, and other the notable unsupported libraries are Regex and Future). As for MSVC10, I don't think they have done much more than promoting the TR1 libraries. However, good news! MSVC11 will feature an almost …

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

>>Well... why would you want to enter "a"?

That's called "fool-proofing a program". Generally, when writing a program that deals with a user (either through console input, command-line input, config-file input, or a GUI), you must assume that the user has an IQ of 0, i.e., that he/she is an absolute imbecile that could be inputting anything and click on all or any buttons. That's often what beta-testing is about, have a user do all sorts of random crap and watch if the program can cope with it.

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

Wow! You are stepping into a problem that is bigger than you can comprehend (no offense). This problem is the general problem of collision detection. To do this correctly and efficiently is a huge deal.

Generally, to solve this problem, you need to solve a number of very difficult problems.

First, you need a means to efficiently determine if two geometries are intersecting (i.e. colliding). There are a number of ways to do this ranging from closed-form minimum-distance formulas between primitive geometric volumes (boxes, cylinders, spheres, etc.), to optimization-based mathematical programming to determine the minimum distance or interception between meshes (set of polygons attached together making up the boundary of a 3D object, i.e. boundary representations (often called "B-Rep" for short)). The latter usually involves efficient mathematical programming algorithms from simple linear programs (e.g. Dual Simplex Method) to quadratic programs (e.g. Ellipsoid Method) to non-linear methods (e.g. general non-linear optimization methods, like LBFGS). In all cases, the methods generally operate only on convex geometries.

Second, if you deal with non-convex geometries, you need to decompose the volumes into a composite of convex geometries (i.e. Convex Decomposition). And that isn't a particularly easy task by itself. Beyond the complexity of just testing sub-meshes for being convex or not, and actually finding a split that works, there are measures involved to figure out the best split for the mesh such that …

Ezzaral commented: Nice post! +15
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You do a cast to unsigned int and then you cast it back to T . This kind of cast generally has undefined behavior, but it is defined that doing (T)(U)t for T t; should yield the same value as t . So, your code is merely checking a standard-defined behavior, if it didn't yield true, it means your compiler is broken.

Your implementation and your strategy for checking if a value is unsigned is not possible, it has too much undefined or implementation-defined behavior, and according to the standard, it shouldn't work in any case. You dangerously run into the possibility of overflow as well.

If you need a meta-function to determine if a type is unsigned or not, you should use the std::is_unsigned template. As in:

#include <type_traits>

template<class T>
inline 
constexpr bool IsValidUnsignedLong(T)
{
    return std::is_unsigned<T>::value;
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>it seems to me like the index method is both cleaner and faster

I think your time measuring method is not good and your optimizations are not turned on, because your performance results are not correct.

I tried this code:

#include <iostream>
#include <vector>

#include "boost/date_time/posix_time/posix_time.hpp"

int main(int argc, char** argv) {
  
  boost::posix_time::ptime t = boost::posix_time::microsec_clock::local_time();
  std::vector<int> vect(100000000,0);
  boost::posix_time::time_duration dt = boost::posix_time::microsec_clock::local_time() - t;
  std::cout << "Initializing an empty vector of 100,000,000 ints in: " << dt.total_milliseconds() << " milliseconds" << std::endl;

  t = boost::posix_time::microsec_clock::local_time();
  for(int i = 0; i != vect.size(); ++i)
    vect[i] = 1;
  dt = boost::posix_time::microsec_clock::local_time() - t;
  std::cout << "Looping a vector 100,000,000 with vect[i] in: " << dt.total_milliseconds() << " milliseconds" << std::endl;

  t = boost::posix_time::microsec_clock::local_time();
  for(auto it = vect.begin(); it != vect.end(); ++it)
    *it = 1;
  dt = boost::posix_time::microsec_clock::local_time() - t;
  std::cout << "Looping a vector 100,000,000 with *it in: " << dt.total_milliseconds() << " milliseconds" << std::endl;

  t = boost::posix_time::microsec_clock::local_time();
  for(int& x : vect)
    x = 1;
  dt = boost::posix_time::microsec_clock::local_time() - t;
  std::cout << "Looping a vector 100,000,000 with range-based for-loop in: " << dt.total_milliseconds() << " milliseconds" << std::endl;

  t = boost::posix_time::microsec_clock::local_time();
  std::for_each(vect.begin(), vect.end(), [](int& x) { x = 1; });
  dt = boost::posix_time::microsec_clock::local_time() - t;
  std::cout << "Looping a vector 100,000,000 with for-each loop in: " << dt.total_milliseconds() << " milliseconds" << std::endl;

  return 0;
};

And compiled with the following:

$ g++ for_loop_perf.cpp -std=c++0x -O3 -lboost_date_time -o for_loop_perf

And the output is, as expected:

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

Lines 54 to 61 are off by one. You should know that indices in C/C++ go from 0 to N-1, that is, for an array hotspot* hotspots[8]; , the indices should go from 0 to 7, not from 1 to 8. This is really basic stuff.

Your default constructor does not initialize the "hotspots" array. And, as rubberman said, this means that the Test->checkHotspot(1) call returns a NULL pointer. When it is dereferenced in the mousewithin() function, you get a crash (segmentation fault or Access Violation, depending on your OS).

Your "screen" class holds dynamically allocated memory, yet you don't have a destructor (and nor do you have a deep-copy constructor and assignment operator). That's an error, you have memory leaking, and possibly more problems down the line. Read my tutorial on RAII for details.

You may have other errors, but start by solving the above-mentioned issues.

tajendra commented: rightly directed +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Inlining functions is, first of all, something that the compiler does. So, the first rule is that the compiler has to be able to find the definition of the function (definition = function body). As Fbody said, the compiler only looks at one "translation unit" at a time (a translation unit (TU) is the technical term for what Fbody (wrongly) calls a "compilation unit"). Basically, a TU is what turns into one object file (.o or .obj), it usually comes from the compilation of a single .cpp file (along with all the header-file code/declarations that it includes).

So, if you have the function bodies in a separate cpp file, and compile them separately, the compiler, when compiling the main TU, will not see the definitions of the functions that are in another TU, and thus, will not be able to inline anything.

Now, if you declare a function prototype with the "inline" keyword, it has two effects. First, it _suggests_ to the compiler that this function should be inlined during the compilation. Second, it marks the function for "internal linkage", meaning that the compiler should look for the function definition within the current translation unit in order to perform the linkage (linkage, here, means to replace every call to that function by either a jump to the address of the function or by an inline expansion of the function's body at the call-site). If the compiler does not find the function definition within the current TU, it will …

NP-complete commented: good info...:) +5
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It is also more efficient (don't use random-access, via an index, if it is not needed). It is also more idiomatic.

Also, the new C++ standard makes it a bit cleaner with the "auto" keyword, as so:

vector<int> myvec; // let's assume it's initialized
for(auto it = myvec.begin( ); it != myvec.end( ); ++it)
{
    // code
    // access by '*it'
}

Also, note that C++11 introduces yet a third and nicer way to do this for-loop, using the range-based syntax:

vector<int> myvec; // let's assume it's initialized
for(int& x : myvec)
{
    // code
    // access by 'x'
}

@ravenous: If the vector is not declared as "volatile", the evaluation of "size" is probably not done more than once. And since STL containers are templates (and thus have function definitions available to the compiler), functions like "begin()" "end()" or "size()" are most probably inlined (so you don't even get the cost of a function call). It is also possible that a clever compiler will be able to optimize the first version (with index) such that it boils down to exactly the same as the second version (with iterators), but, in theory, the iterator version has the best chance of being more efficient.

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

Basically, optimization flags play a big role in increasing the performance of an application.

You need to first make sure you compile under "Release" mode, which will disable debugging hooks and features (so you won't be able to stop the program with break-points and step through it). Those debugging hooks are not necessary once you have finished debugging the application.

Then, you can enable a number of optimizations. Basically, you can choose between fast code ( /O2 ) or small code ( /O1 ). And you can also enable global optimizations ( /GL ). In general, the fastest code is generated with the /Ox compilation flag. I'm not familiar enough with Visual C++ build option menus to direct you to where you can change those settings, but you get the general idea: go through the build options and enable anything that says "optimization". At worst, you can add /Ox to the custom compilation flags (somewhere in the menus). Here is a complete list of compilation flags for MSVC. Here is an overview of high-end optimizations in MSVC. Basically, if you have knowledge of your architecture's hardware accelerations, you can specify that in order to make use of them to increase performance.

After disabling debugging and enabling all optimizations, your program should function exactly the same as before, just a lot faster (4-5 times faster). If it doesn't work correctly anymore, then you have bugs in your program.

Cainer commented: Perfect answer. Thank you very much. +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I had difficulty using the vector-of-boolean interface.

Exactly, that's the main argument that people make against the vector-of-bool specialization. Let me give a bit more background on this problem. The original decision to include a specialization was from the memory optimization point-of-view. But people soon realized that, even though the vector-of-bool provides an interface which essentially looks like the general vector template, it makes some hidden assumptions (like the proxy-object for lvalue indexing) that essentially break the interface. It was a simple mistake, nobody's perfect, including the architects of the STL. For example, in the case of indexing, they were satisfied by the fact that the proxy-object could act as a bool& variable in a statement like vect_bool[i] = true; , but the problem is that you cannot bind a bool& variable to this lvalue obtained from the indexing (including sending it to a function that takes a bool& parameter), i.e., you cannot do bool& b_ref = vect_bool[i]; .

The gist of the debate is this:

On one side, the more purist side, people argue that, by definition, the reference that is returned by the non-const indexing of any STL container is not required to be T& , it is only required to be of the type std::vector<T>::reference which may or may not be T& . Just like random-access iterator is not required to be T* (but it could), the only requirement is that it acts in a way that is similar to a T* . Technically …

NathanOliver commented: Great explanation +9
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Here's my opinion on it (compilers, not IDE or build-systems):

Portability: GCC (GNU Compiler Collection)
Compilation Speed: BCB (Borland C++ Builder)
Code Optimization: ICC (Intel Compiler Collection)
Usefulness of compilation warnings and errors: GCC
Debugging capabilities: MSVC 2010 (Microsoft Visual C++ 2010)
Strict standard compliance: Comeau and ICC (using the EDG front-end)

Overall, GCC is a great option and MSVC is also pretty good, expecially considering both are free. The BCB compiler is also very good but a bit isoteric (has the same back-end as the Delphi compiler, which has some visible impacts in the form of some non-standard things, but it also gives it a much better compilation speed). As for code optimization, nothing beats the Intel compilers on Intel systems, but GCC is coming close to catching up to ICC, while MSVC is still shamefully lagging behind by a significant margin (and I don't know the current status of BCB, but earlier versions used to beat both GCC and MSVC like a rented mule while almost matching up to ICC, but that is probably not the case anymore because ICC, GCC and MSVC have improved a lot since then). GCC has also improved (4.5+) a lot when it comes to compilation times (my code-base used to take about 45min to compile entirely in pre-4.5 versions of GCC, now it takes about 15min with 4.6.2 version).

tajendra commented: useful compilation +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>There is a lot of tutorials but they are all without code example

That's normal. There is a big difference between learning a programming language and learning software design. First, you need to get familiar with the syntax and idioms of a particular programming language. And learning to create classes (including inheritance, virtual functions, constructors/destructor, etc.) is part of learning the programming language (if it has syntax to do this, of course, and C++ does). Then, once reasonably comfortable with at least one programming language that makes OO code easy to write, you can learn about OO analysis and design, and apply it with your language of choice.

It's the same with computer science textbooks / papers that show you algorithms in pseudo-code instead of actual code in one language or another, because the actual programming language matters only when it comes to the details.

If you read OO tutorials or articles and cannot figure out how the things that are discussed translate into C++ code, then it means you need to get more knowledge of C++. Object-oriented programming is a way in which you organize and think your software, it's not about how you exactly write it (that depends on the language, in C++ or Java, OOP is done essentially the same, but the details are (very) different).

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

Well, it is certainly useless to do it this way, but if you do, then yes, the compiler will optimize this away. If it doesn't, then it is a very pessimizing compiler (pessimizing = anti-optimizing). All modern compilers do this.

In general, the rule of optimizations is the "as if" rule, that is, the optimized code should behave as if it was the verbatim translation of the original code (i.e. not optimized in any way). However, there are two notable exceptions to this rule, that is, elision of temporaries and return-value optimization. The former means that if a temporary is created and immediately copied into another variable, then it can sometimes be optimized away (but it depends on the context). The latter means that the value that is returned from a function can be created in-place of the variable it is going to get copied to (again, under some circumstances).

Because, in C++, you can execute code during the constructors/destructor of an object, it means that optimizing away the creation of a temporary object technically breaks the "as if" rule. But, because those optimizations are so important for performance, the C++ standard allows it, and all decent compilers take advantage of this permission. So, this is something to keep in mind when writing constructors/destructor code, that is, you can't really predict how many times they will be called, all you can rely on is that anything that is created is eventually destroyed (i.e. every constructor call will eventually …