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

Each of us knows something but all of us know everything, and hopefully one day, we'll learn to listen to each other. - Jim & me

cproger commented: haha +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yeah, it's quite sad. Although, it was expected for some time.

@Warrens80: Bringing down the apartheid is no mean feat. And be prepared for a flurry of down-votes.

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

I was just teasing.

diafol commented: I know, so was I - "infinities" - but I guess it didn't work :( +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

As software engineering is similar in many ways to architecture, there is a principle that they share: "Form follows function". The principle is summarized as the fact that the form that a construction takes depends primarily on the function or purpose intended for it.

The reason I point this out is that you are asking about the form that code should take, without explaining the purpose or function that the code should accomplish. That can't work. You have to explain the function before you can determine what the best form is.

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

I don't agree that "the title says it all". I have no idea what your question is. Programming involves creating and using functions and classes, how could it possibly be not "ok", if you can't create / use functions and classes, you can't do anything. It's like asking "is using a hammer and nails 'ok' for a carpenter?". Please explain what you mean more clearly, and we'll be happy to help.

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

Here is some food for thoughts, imagine you have this scenario:

std::queue<int> line1;
for (int i = 1; i <= 10; i++)
    line1.push(i);

std::vector<std::vector<int>> returns1(2);
std::vector<std::thread> threads1;
for (int i = 0; i < 2; i++)
    threads1.emplace_back(DoTransaction, std::ref(line1), std::ref(returns1[i]), i + 1);

std::queue<int> line2;
for (int i = 1; i <= 10; i++)
    line2.push(i);

std::vector<std::vector<int>> returns2(2);
std::vector<std::thread> threads2;
for (int i = 0; i < 2; i++)
    threads2.emplace_back(DoTransaction, std::ref(line2), std::ref(returns2[i]), i + 1);

Do you see a problem here?

The problem here is that whether the mutex is a global variable or a local static variable, the problem remains the same: both sets of threads will lock the same mutex even though they are using different queues.

The only viable solution is to associate the mutex with the queue, somehow. A cheap and easy solution is just to pass the mutex to the function along with the queue. A somewhat fancier solution would be to implement a thread-safe queue class, which could be as simple as just wrapping a mutex and a queue into a simple class that does what you need to use it for. Another solution might be to use something like this class I wrote a while back.

Another typical solution is just to use a functor class:

struct Transactioner {
  std::queue<int> line;
  std::mutex mtx;

  void serveCustomers(std::vector<int> & customersServed, int wait)
  {
    while (!line.empty())
    {
      mtx.lock();
      int val = line.front(); 
      line.pop();
      mtx.unlock();
      std::cout << val << "\t" << wait << std::endl;
      customersServed.push_back(val); …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

It would appear that you and I have similar sensibilities about grammar. We can't expect others to have the same erudition as you and I. If they make mistakes, let them, they're only demonstrating their ineptitude to you and me.

And I ain't an expert in grammar either, although I fancy myself a connaisseur.

ddanbe commented: Nice example of the use of I and me! +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This thing could be done with any language, i.e., it is possible to do it in any language. However, certain languages are not really appropriate for this problem. This is a fairly low-level, heavy-lifting application, meaning that high-level, light-work languages are not going to be very appropriate. On that criteria, you can rule out VB.NET and C# right off the bat, because these languages are geared towards the rapid development of user-facing applications, not for heavy-lifting. PHP might be useful for its "network oriented" qualities, maybe as a front-end to your application. But for the most part, you'll have to write it in a heavy-lifting language like C or C++. This is really the kind of application that C++ is geared towards.

You'll have to define more precisely what your task is. You said that what I described was exactly what you meant, but I described things if very vague and general terms, not really something that can be "exact". You need to provide a more specific definition of your problem.

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

The problem is that your reverse function takes its parameters by value, causing a (shallow) copy of the stacks:

void Stack::Reverc(Stack s,Stack d,Stack c)

This is wrong, for a few reasons. First of all, the stack that you seem to be reversing within that function is the s stack, but you really should be reversing the this stack, and this is the way that you call it in the main() function (i.e. you call reverse on a stack object and then print the result). In other words, with that correction, you get this:

void Stack::Reverc(Stack d, Stack c)
{
    int x;  
    while(!this->IsEmpty())
    {
        x = this->Pop();
        d.push(x);
    }
    while(!d.IsEmpty())
    {
        x=d.Pop();
        c.push(x);
    }
    while(!c.IsEmpty())
    {
        x = c.Pop();
        this->push(x);
    }
}

At this point, the result should be "correct", but there are still a couple of issues with the code. One issue, which is true in general, is that if you have variables like c and d that are only needed within the reversing function, then you should not pass them as parameters to the function, but instead, create them locally within the function:

void Stack::Reverc()
{
    Stack d, c;
    while(!this->IsEmpty())
        d.push( this->Pop() );
    while(!d.IsEmpty())
        c.push( d.Pop() );
    while(!c.IsEmpty())
        this->push( c.Pop() );
}

Another issue is that your code is leaking memory all over the place. The general rule in C++ is that every new allocation of memory must have a corresponding delete. You did this correctly in the push / pop functions by …

ddanbe commented: Very thorough! +15
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The saying I came up with about pointers is this:
"Pointers: Beginners hate them; experts hide them."

The thing that makes pointers "hard" for some is that they are too simple, ironically. A pointer is nothing more than a number (integer) that uniquely identifies a location in memory (an address). That's all they are, nothing more. It's what they are not that is complicated for some to deal with, for example:

  • Pointers do not own the memory at the address, i.e., having a pointer to a location does not guarantee that that memory will remain valid.
  • Pointers do not always have a valid address value, i.e., they can point anywhere, including arbitrary or invalid addresses.
  • Pointers do not copy the pointed-to memory when they are themselves copied.
  • Pointers do not know what they are pointing to (nowhere, start / middle / end of array, stack / heap memory, etc.), and there is generally no way to find out.
  • Pointers are not managed by a garbage collector.

Beginners, especially those who come from a "higher-level" language where pointers are completely hidden, make mistakes, involving pointers and memory management, precisely because they assume one or many of the things listed above, or at least, they code as if to assume them, or, they are just really careless with pointers out of a habit they have developed in their "native" language. That's why beginners hate pointers.

Experts (that is to say, people with more experience in C++) deal with pointers by …

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

First you get a self proclaimed expert who says it is absolutely wrong to ask for other people to write code for you

It is absolutely wrong to ask for other people to write code for you. That is stated in the Rules of Daniweb:

"Do provide evidence of having done some work yourself if posting questions from school or work assignments"

We get a lot of people who simply post their homework question and demand to have full working code for it. We generally tell them that nobody will do their homework for them, because it is (1) against the rules, (2) probably against the school's ethics policies, and (3) not helpful to them, as they should do their homeworks by themselves if they want to learn.

Then you find this self proclaimed expert begging for other people to give them code here--> http://www.daniweb.com/software-development/cpp/threads/144681/way-to-do-this

The two threads you are referring to are 5 years apart. I don't know about you, but 5 years is plenty enough of time to go from needing help to being able to help others. And I'm having trouble finding where iamthwee self-proclaims to be an expert.

It's hard to take you seriously. This sounds a bit too much like you're trying to smear iamthwee because he ruffled a few of your feathers.

It's no secret that iamthwee can be a bit obtuse at times, even as far as getting dangerously near a "keep it pleasant" infraction. …

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

I don't think anyone will bother with human cloning

I don't know if you could consider this a form of cloning, but I see much more promise in the "cloning" of organs, i.e., artificially growing real organs out of your own (repaired) genes in order to replace your used / damaged organs. I think that could have a significant impact. At first, it would be just to eliminate the need for organ donors, then it would become a common procedure for all sorts of problems, and then it could become a means to extend life significantly.

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

If you want to use a fixed selection of types, then you should use Boost.Variant (discriminated union type, similar to that old C-style variant type in windows.h).

If you want to use any types, then you should use Boost.Any, which is a kind of ultimate type-erasure device.

And if you want to take any type and turn it into a serial stream (like a string), then you should use a serialization scheme, like Boost.Serialization.

These are, generally, three separate problem, so, you have to figure out which one is really the one you want.

cambalinho commented: thanks +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The main program is a function. The question makes no sense. The alternatives: "within a function" instead of "within a function".

You would open / close a file within any function for the same reason that you would open / close a file with the main function, i.e., because you need to read from or write to the file.

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

Well, first of all, the two options are not mutually exclusive, there is not problem with providing both a factory function (create) and a polymorphic cloning function, it is, in fact, very common. Something like this:

class Object {
  public:
    // NEVER FORGET THE VIRTUAL DESTRUCTOR!!!
    virtual ~Object() { };

    virtual int getInt() { return 0; };

    virtual unique_ptr<Object> clone() const {
      return unique_ptr<Object>(new Object(*this));
    };

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


class One : public Object {
  public:

    virtual int getInt(){return 1;}

    virtual unique_ptr<Object> clone() const {
      return unique_ptr<Object>(new One(*this));
    };

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

The use of the unique_ptr in the factory function is just because they are implicitely moveable into a shared_ptr, so, there is no reason to "commit yourself" to the shared_ptr in the factory function. Instead, let the calling context determine if the caller of the factory function wants to put the result in a shared-pointer or in a unique-pointer. But if you want to avoid using unique-pointers (since they are C++11 only, as opposed to shared-pointers which exist since TR1 and are available in Boost), then using shared_ptr is also perfectly acceptable.

Is it possible to achieve this kind of functionality without forcing the user to add a specific function to each class?

This is a bit difficult. As far as I know, there is no clever trick to achieve this in a really …

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

What I'm opposed to is the lack of quantification of anything. When it says "could potentially pose a catastrophic EMP threat", there's no measure in that statement: "potentially" could mean anywhere from 99% chance to one chance in one trillion; and, "catastrophic" could mean anything from wiping out all of the human race to causing significant damage to the infrastructure (require significant repairs, and possibly an extended down-time). This kind of alarmist language with no real measure or proportions irritates me to the highest degree.

From the 2010 report I glanced over (which was rather poor quality, from my judgement as an engineer who has studied those kinds of effects), even they seem to conclude that there are serious concerns about preserving the equipment and avoiding wide-spread power failure due to a cascade of failed equipment. But it seems limited to bursting relays and burned PLCs, and they do a lot of wild speculations about the likelihood of equipment to be damaged. And there are many questionable methods in their study, like, for instance, using upset-limit voltages to decide if a pulse of a certain voltage will damage them, without considering the power density. Also, they seem to model all plugged-in electrical equipment as being a large antenna (the cable) plugged into the equipment, without modeling ground capacitance and dynamic response of the equipment and transmission equipment. Long story short, it does not convince me that there is very much of a threat except for a few mishaps that would …

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

What if all the power house countries went to war with each other and we all sent EMPS at each other

You watch too many movies. You are not alone though, even the US Air Force had to make a video "Hollywood vs EMPs" to dispell the hollywood myths about the power and impact of EMPs. For one, the power required to send a real wide-spread EMP is only achievable with nuclear weapons. And if you were to generate enough EMPs to seriously cripple the entire power grid or tele-comm systems, it's not the outages you should be worried about but the nuclear fallouts. On a more practical level, EMPs can be used to induce glitches on targeted systems, possibly temporarily shutting them down or damaging some electronics components. But the effect is very limited (either very narrowly targeted, or wide-spread with very little impact except a few minor glitches). It is nothing like in the movies, that's called fiction.

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

Knock out the satellites and all communications

Easier said than done, there are far so many satellites that a large number of satellites could be "knocked out" without really compromising the whole system. Global telecommunication systems are massively redundant by design, there aren't really any single points of failure in it. And also, how exactly can you knock out a satellite? Satellites on geosync orbits (where most tele-com sats are, except of a few russian sats on high elliptical orbits) are very far away (about 36,000 km altitude), are not affected by problems like space debris, are too far to be destroyed remotely, have safety low-gain antennas in case attitude control is lost, and are designed to run for decades before needing to be replaced. They are not about to disappear, I can tell you that much. Even GPS satellites are quite safe, even though they are much closer to the Earth. The more dangerous zones for satellites are in low-Earth orbits (LEO), where observation satellites are (weather sats, spy sats, etc.).

The Internet is not about to go down either, after all, it was designed for redundancy and failure safety in the first place (i.e., military networks relayed through planes, helicopters, vehicles, and bases, which are all subject to suddenly disappearing). The only thing that really threatens the internet is people with economic motive to compromise it's inherent openness and neutrality, which are the key aspects of its fail-safety and redundancies.

computers will run at 5.2 …

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

Whatever happened to just failing those cheaters? If the prof has found out that one of his student took an answer from here or elsewhere, that's plagarism, that's an automatic zero on the assignment / exam. That's how it is here (if not worse). If the prof does not have the chutzpah to fail his cheating students, it's his problem, not yours.

It's very easy these days for CS courses to have anti-plagarism filters (take code and search for exact matches on the web).

JeffGrigg commented: Yes; they need to have and use a policy that works. +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The closest you can get is probably something like this:

class Data {
  // ....

  private:
    static const double* getInitValues() {
      static const double arr[] = {1.0,4.0,5.0};
      return arr;
    };

  public:

    Data() : V(std::vector<double>(getInitValues(), getInitValues() + 3)) 
    {
    };

};

But frankly, I don't see the point of going through all this trouble just to either (1) avoid using a C++11 feature, or (2) avoid putting three simple statements in the constructor body.

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

I still remember the good old days (only a few years ago), when any given search on a devel problem would result in a number of results from different sites (forums and mailing-lists), and when SO and Daniweb were more or less as likely to hit on searches. Now, it seems that Google has somehow made sure that the top three to five search results are always for StackOverflow, regardless of how unrelated the threads are to the actual search terms. Very often, I find myself making a search, and almost automatically scroll down to the middle / end of the first page of results, because I so often find the first results to be irrelevant stuff (irrelevant to my question) from the "preferred sites". I'm seriously thinking finding an alternative search engine (I hear duckduckgo is not too bad, any other ideas?).

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

I would like to see the beginning of creation

Lol! Don't forget to tell Eve not to eat that apple. Or better, just cut down that tree, better not take any chances. If you don't go back that far, you can at least warn Jonah to watch out for big fishes. Or tell Lot's daughters to leave town before their father gives them up to be raped by an angry mob.

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

as a beginner, i managed to do this much (85%) and i am facing the problems of "Cannot find or open the PDB file."

PDB files are files that are specific to Visual Studio projects. This is a problem with setting up your C++ project. Are you able to run a simple "Hello World" program? Did you make sure the follow all the steps to create a win32 console application in Visual Studio?

You might want to consider using a simpler (lighter-weight) IDE like CodeBlocks instead (make sure the download / install the version with MinGW). It uses a simpler (and less troublesome) project configuration system than Visual Studio.

am i supposed to place the files in a special place for the program to read it?

If you provide absolute paths, then it does not matter. If you provide relative paths, then they will be relative to the place where the executable runs from (which is kind of unclear in Visual Studio). Just locate the folder in which the "*.exe" file for you project was generated (it is usually in the "debug" or "release" directories of your project folder). I'm sorry, it's been a long time since I've used Visual Studio with default build configurations (I, like most experts, use other external build configuration-script systems).

Also, your input method:

cout << "Input the name of the input file: " << endl;
cin >> inFileName;
inFile.open(inFileName.c_str());

will only capture the first …

ddanbe commented: No one can beat the deepness of your explanations. +15
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This speaks to the point I made in the last post. The code you just posted makes no sense at all.

And obviously, when I posted the simple example of what a "functor" is, I didn't mean that as a suggestion for something to try for your specific problem. It was just the simplest possible example I could come up with of something that can be called a "functor", to illustrate the concept. It had nothing to do with your specific problem. You asked for an explanation of what a "functor" is, and I delivered that. A functor is a very general and fundamental concept in C++, and so, I had to explain it in very general terms, having nothing to do directly with your specific problem.

but i get errors when i change the Soma()

What do you mean?!?!? You cannot "change the Soma()". That makes no sense at all. A function has one definition and only one definition (that's the fundamental C++ rule, called the "One Definition Rule"). That definition is fixed during compilation, and can never be changed after that.

You can create a variable that points to a function, that's called a function-pointer. You can create a variable of a class type like std::function which can be made to point to any callable "something". But these are always just pointing to a function which has one unique and immutable definition.

And the error itself is due to this syntax:

a.Soma(int a, int b) …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

the foo structure accept parameters?

No. The call operator definition is as follows:

void operator()() const { };

Which means:
void: This function has no return value.
operator(): This function is invoked by "calling" the object like you would call a function.
(): This function takes no parameters.
const: This function does not modify the object on which it is called.
{ };: This is the function body (which I left empty).

So, the answer is: No, an functor of type "Foo" is called with no parameters.

how can i change the funtion?

What do you mean? I left the body of the function empty, but, of course, you would normally write code in that function-body. If that's what you mean by "change the function", then that's that, i.e., you can change the function when you open the source file in a text editor or IDE and you write code in the function-body.

If you mean to somehow assign the call operator to trigger the call of some other function, then that's impossible in this code. In C++, a function is just a function, you cannot "change" it in that sense. If you have a variable like a function-pointer or a std::function object, then this is different, these are variables that are meant to be changed to whatever value you want. A "function" is not a variable, it's immutable (cannot be changed).

I'm gonna be frank here, I must say that you seem be …

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

No. A functor is just a short for "function object" or "callable object". It is a callable thing. For example, this is a functor:

struct Foo {
  void operator()() const { };
};

Because if you have an object declared as something like Foo f;, then you can "call" it, as in, you can do f();.

Technically, almost anything that is callable is a "functor". A function pointer is a functor, because it is an object (a pointer is a variable, which is an object) and it is callable. A lambda expression is a functor too. The standard class template std::function is a functor too, with the special feature that it can encapsulate any other functor you give it.

Traditionally, however, the term functor is mostly used to describe an object of a class like the "Foo" class in the above snippet. In other words, an object of a class that has a "call operator", i.e. the operator(). But in modern C++, with things like std::function, std::bind and lambdas, that line has become a bit more blurred. I just use the term "functor" for any object that is callable.

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

As far as I know, the standard does not provide a specialization of std::function for "variadic functions" (also called "variable argument functions", or just var-arg functions). When you use the ellipses alone (not part of a variadic template syntax), it declares a variadic function, which is a special kind of function that was inherited from C to allow for a variable amount of parameters (e.g., to allow the implementation of functions like printf or scanf).

I am not too surprised that the standard committee overlooked this possibility since variadic functions are antiquated and unsafe. It is generally not recommended to use them, ever. And one of the main purposes of variadic templates is to replace variadic functions with a type-safe solution. In other words, forget about variadic functions, they are just part of the C legacy that C++ has to drag around.

If variadic functions could be used with std::function, your code would have to look like this:

class event2
{
public:
    typedef std::function<void(...)> OnSomethingHandler;


    template <typename... Args>
    void operator() (Args&&... args)
    {
        eventwithoutarg(std::forward<Args>(args)...);
    }

    event & operator = (OnSomethingHandler Handler)
    {
        eventwithoutarg = Handler;
        return *this;
    }

private:
    OnSomethingHandler eventwithoutarg;
};

Except that this will not work because the type std::function<void(...)> is not defined by the standard (AFAIK).

If I understand what you are trying to do, I think you need to do a classic type-erasure strategy. Here is what I mean:

class events {
  private:
    // have a placeholder base-type:
    struct base {
      virtual ~base(); …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

can i use the instance\object name?

Not for the definition. The member is a static data member, meaning that it is linked to the class, not an object. However, for expressions, you can access the static data member through the object, but this is just a syntax feature, the static member is still the same for all objects of the same class. Here is an extension to the example:

class Foo {
  public:
    static int bar;  // <- 'declaration'
};

int Foo::bar = 42;  // <- 'definition'

int main() {
  Foo f;
  f.bar = 69;  // OK
  std::cout << Foo::bar << std::endl; // <- this will print '69'
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

No, you cannot. You can have one definition of the static data member (i.e., constructor / initialization of the data member). But after that, you cannot modify the static member at the global scope, because that would have to be either an expression (which is not allowed), or a second definition (which would break the C++ One Definition Rule (ODR)). Of course, you can modify the static data member within any function, but not at global scope.

Here is a simple example:

class Foo {
  public:
    static int bar;  // <- 'declaration'
};

int Foo::bar = 42;  // <- 'definition'

Foo::bar = 69;  // ERROR: expressions not allowed at global scope.

int Foo::bar = 69;  // ERROR: re-definition of 'Foo::bar'

int main() {
  Foo::bar = 69;  // OK
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

you're saying that I cannot create 1 program that will be cross platform (in c++) but I can make a library that is cross platform

Whether you create a program or a library, the situation is the same. Usually, it is more practical to make a cross-platform library (i.e., encapsulate the platform-specific code in a library). However, you could also do it in a program.

by swapping in correct code at compile time (presumably using #ifdef directives).

Yes. You swap the correct code at compile time, either using some #ifdef stuff in the code, or using the build script to swap between distinct cpp files that implement the same functions but in a different way (for each platform).

Then if I want my code to work on two systems I compile it twice, once with each OS specified?

Yes. This is often inevitable, depending on how different the platforms are. Some platforms use completely different binary formats for executables and libraries. Specifically, Windows versus Linux/Unix/BSD (i.e., POSIX). Among different versions of Linux and other similar systems, things will mostly work without recompilation, as long as the target architecture (instruction set) is general enough (like i386 for example). But executable programs for very different platforms like Mac, Linux and Windows are not going to work between them, you have to recompile for each platform.

When we talk about doing cross-platform development in C/C++ (or any other native compiled language), we are just talking about the …

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

I see the same problem (the username spilling over under the faint line) on my browser: Chromium in Linux(Kubuntu).

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

I think Labdabeta misunderstood your code. He thought that your declaration of Printed was meant to be a function pointer to a function that takes no argument and returns a events<> object. In reality, your declaration of Printed was a declaration of a data member of type events<> with an in-declaration initializer (that uses the new {} uniform initialization syntax) to an empty lambda functor. Later, when he initializes the Printed function pointer to point to a lambda expression, it cannot work because the lambda expression must return an events<> object, instead of void. In other words, it doesn't work.

cambalinho commented: thanks +2
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I tested the code (that I posted in my last post, and using your implementation of the "events" class) and it all works, no warnings, no errors, and runs as expected, with the correct output.

if i'm overloading '()' operator, why i can't use it, outside of main?

It does not matter what you overload or not, you cannot execute code outside of any function's body. It's that simple. See this simple code:

// these lines are fine, 
//  they are 'definitions' of global variables. 
int a = 2;
int b = 3;

// this line is OK too, 
//  it's also a 'definition' of a global var.
int c = a + b;

// this line is an ERROR!
//  it's an 'expression' not a 'definition'
c = a * b;

At the global scope, you are allowed to declare stuff like classes, functions and variables, and you are allowed to define stuff like functions (by providing a body for the function) and variables (by providing an initial value / constructor-invocation). But, you are not allowed to write expressions that need to be evaluated. The compiler only issues "static initialization code" for the global objects, it cannot accomodate general expression evaluations (unless they are made a part of the construction of one of the global variables).

When you tried to give a new value to the data member a.Printed, that was an expression, just like the c = a * b; expression above, which is …

cambalinho commented: thanks +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yeah, the most common use for static member functions is for factory functions, whether it is a straight-up "Create()" function to create an object of the class, or whether it is for a set of factory functions like "fromString" and stuff (i.e., Java-style conversion functions, when people are not familiar with or not comfortable with C++'s conversion operators, or they just want a more explicit syntax).

There are some other special purposes for static member functions. Most of the time, it just boils down to semantics. If a given function clearly and only belongs to the class, but it does not need to be called on an object of that class or does not take one (or more) as an argument to the function, then the only way to really tie it to the class is to make it a static member function. This is the same argument as for static data members.

And the name pollution can be a real concern sometimes. As a rule of thumb, if you have a class named "Foo" and you want to create a static member function named "Bar", and you are considering making that function a free-function (in the namespace/global scope) instead. If, while making the function a free-function, you would have to rename it to something like "FooBar" in order to make it make sense, then you are probably better off leaving it as a static member function, i.e., calling it as "Foo::Bar". This is the basic "semantics test" to figure …

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

The problem is that you cannot run code in the global scope. The global scope is only for declarations or definitions, not for expressions (executing code). You have to move your setting for the Printed functor in the main function:

#include <iostream>
#include <string>
#include "events.h"

using namespace std;

class test
{
    public:
    events<> Printed{[]() { ; }};
    void write(string a)
    {
        cout << a;
        Printed();
    }

};


int main()
{
    test a;

    a.Printed = events<>{[]()
    {
        cout << "\nMessage printed\n";
    }};

    a.write("hello world");
    cin.get();
    return 0;
}

I think this should work, although I have no idea how "events" is set up.

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

The way this is done is quite simple. It's all a matter of creating an interface (i.e., set of functions or classes) that is not specific to any particular platform. Then, you create an implementation that fulfills that interface for each platform you want to support in a way that hides all the platform-specific code. This way, you need to compile your library for each platform, but for the user of the library, it all appears to be the same because the user only interacts with the interface (not with the encapsulated implementation details).

If you take the example of SDL. The Unix/Linux/Mac API for creating and dealing with a window is very different from the Win32 API used in Windows. However, in abstract terms, they do the same things, e.g., create a window, set some pixel values on it, have "redraw" events, etc... So, the SDL library has created a set of abstractions, like SDL "surfaces", that encapsulate those essential and common functionalities between the platforms. So, as a user of SDL, you only have to deal with those, and you can remain oblivious to the implementation details (i.e., what actual API calls are done under-the-hood). Then, the SDL implementers simply create source files (.c, .cpp files) for each platform, and that use the correct API calls to fulfill the "contract" or functionality that is exposed by the platform-agnostic interface.

This is really the key to creating a cross-platform library that requires the use of platform-specific API calls. You …

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

The operator -- is just the decrement operator, i.e., the opposite of ++.

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

That function could have been written like below, where x is an unitialized variable until it is set to the parameter.

Absolutely not! If you think that, you did not get the point, at all!

If I use the implementation you provided into this program:

#include <iostream>

int get_first_value(int value) {
  static int x;
  x = value;
  return x;
};

int main() {
  std::cout << get_first_value(42) << std::endl;
  std::cout << get_first_value(69) << std::endl;
};

then, the resulting output is:

$ ./test_static_local
42
69

If I use my original implementation:

#include <iostream>

int get_first_value(int value) {
  static int x = value;
  return x;
};

int main() {
  std::cout << get_first_value(42) << std::endl;
  std::cout << get_first_value(69) << std::endl;
};

then, the output is:

$ ./test_static_local
42
42

You can try it for yourself, you are skeptic about it.

Because the value of x is initialized the first time control flows over it, that is, with the value 42 (which is passed on the first call). So, on the second call, even though 69 is passed, the value of x remains the same, i.e., 42, because the variable is already initialized, and won't be initialized again.

The get_first_value() function he posted is not initializing x, it is just simply setting x to the value of the parameter. That isn't the same thing as initializing x.

By "initialized", I mean initialized, as defined in the standard, which means, it is constructed (i.e., …

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

Yo mama is so fat that when she went to a Star Wars convention in a "Slave Leia" costume, she won the price for best Jabba the Hutt costume.

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

Ok, to settle this, let's just look at what the C++ standard says. Here is the relevant section (that I already quoted in another recent thread where the properties of those variables is a critical part of the design) about block-scope variables (i.e., local variables) with static storage duration. Section 6.7/4:

The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

The translation into plain English is that if the variable has a trivial constructor (i.e. a POD …

deceptikon commented: For quoting the standard. :) +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, I have to correct the correction because what AD said is wrong. Local variables (defined in a function) with static storage duration (with static keyword) are created and initialized the first time control flows over that code (i.e., the first time the function is called). MandrewP was entirely correct. The C++ standard is 100% clear on this issue, and I don't know of any compiler that does not apply this correctly.

For example, this code is perfectly correct:

int get_first_value(int value) {
  static int x = value;
  return x;
};

int main() {
  std::cout << get_first_value(42) << std::endl;
  std::cout << get_first_value(69) << std::endl;
};

And it prints out 42 and 42, as expected. And, of course, the above code would be impossible if local static variables were "just like all other global variables".

Of course, if the type is just an integer (not a class with a non-trivial constructor) and the value it's initialized with is a compile-time constant, then that would allow the compiler to optimize this code by making it a statically-initialized static-duration variable, i.e., a normal global variable. In that sense, in this particular example, what AD said is probably true in practice, but it's an "as if" optimization case (i.e., it can be made into a global variable while looking "as if" it was a local static variable).

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

No, I think you would do well to just put the "OOPL" term out of your vocabulary. It's largely a meaningless term, IMHO.

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

For pre-C++11 compilers, i.e. C++03 compilers, you should use the Boost libraries, which is where all the standard library additions came from, and will likely come from in the future. In this case, the Boost.Thread library is what you are looking for.

However, I doubt that your idea is really the best way to achieve what you want. To me, it sounds like the appropriate solution is the "futures and promises" method. See the boost::future documentation for example. The idea is pretty simple, you create a "promise" and an associated "future" (expectation of a value being delivered). The thread takes the "promise" and is responsible for fulfilling it at some point (i.e., giving it a value). The "main" thread keeps the "future" and can either wait for it to be fulfilled or regularly check it. The reason for this separation has to do with avoiding locks, probably in a similar way as you were thinking of using atomics.

By the way, standard atomics only work for trivially copyable types.

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

As deceptikon says, object-oriented programming has a very plastic definition. Whenever an "OOP" language incorporates a clever feature, some start calling it a fundamental part of the paradigm, to the exclusion of any language that doesn't incorporate the same feature, or not to the same extent or ease of use.

In some sense, there's a Borg-like assimilation effect at play. Holding OOP on a pedistal often implies that any other "clever" programming pattern or technique must be somehow made a part of OOP, both to reinforce the glory of OOP, and to deny that there are clever non-OOP solutions to certain problems.

If you precisely define OOP as a certain set of mechanisms (e.g., run-time polymorphism) and certain design patterns, then you have to live with the fact that it will only be an appropriate paradigm to use in some situations, but not all. Some people can't live with that idea. I've met some of them, you can see, in their body language, the strong physical discomfort when you demonstrate to them a good programming technique that does not draw anything from OOP or follow any of its doctrines.

At the end of the day, programming paradigms are just about the way you understand the code. And describing "the way you understand the code" is difficult to do in concrete terms. It's often difficult to describe it in UML diagrams too, due to their limited descriptive power.

I don't think it is useful to use the term OOP to mean …

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

Yo mama is so fat, that the GPS calculations have to be corrected for the gravity field she generates.

cproger commented: haha +0
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Sorry, you're not allowed to do that. Try begging Dani for permission or participating more in the community to gain additional privileges.

This site has a few restrictions for completely new members. These are designed to prevent spam and spam-bots. As any other popular forum site, spam is a recurring issue. There have been a number of specific spamming strategies that required some of the restrictions. For example, at one point, some spammers would create an account and start spamming and phishing all the other members with a massive "private messages" campaign, so the privilege to send PMs is now granted after 5 posts (or 10, I'm not sure). That solved it.

So, that's the explanation. Once you have made 5 (or 10) posts, you get all the same "privileges" as any other member (except mods and admins, of course).

which moron has developed your website and page?

That would be mostly Dani herself. And "moron" couldn't be further from the truth when it comes to describing Dani.

it has dropped in rank cause of such foolish response

No, the drop in ranking is mostly due to Google's many recent updates to their search engine. Read more about it here, here, and here.

2.13MB lol maybe you should really beg for a better page developer.

I don't understand. Is 2.13MB really that much? And is 0.029 seconds really that long? I'm not a web developer or …

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

When people say that C++ isn't a real OOPL, they mean one of two things:

(1) C++'s implementation of OOP mechanisms (inheritance, virtual functions, etc..) is not "pure" OOP, or not pure enough.

(2) C++ is a multi-paradigm language, and OOP just happens to be one of the main paradigms that it directly supports, but not the only one.

I fall in the second category, as most experienced C++ programmers do.

And I despise people who fall in the first category, we call them "OOP zealots". It's true that C++'s implementation of OOP does not fall perfectly in line with the rigid dogmatic definition of OOP (or how an OOPL should work), but any reasonable person would say that it's "close enough", and would probably also say "who cares?". And if I'm gonna be frank, people who attack C++ as not being a "true" OOPL are often just making pity "grasping at straws" arguments against C++, a language they love to hate. Don't listen to those fools.

In my perspective, OOP was the awesome new way to program back in the late 80s and early 90s. Some still see it that way, but they just haven't kept up with the times. Modern C++ code makes very limited use of classic OOP style. Yes, OOP is "classic", not new or modern. I remember, when I first learned to program, in the late 90s, OOP was already the classic programming style.

A big part of this issue has to do with the …

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

A recurring problem many newcomers face when tackling C++ is the compilation process, from sources to binaries. This tutorial will detail that process. It will be especially useful for people only familiar with higher-level languages (if any), but veterans of one or more native languages (C, Fortran, C++, D, etc.) might still learn a thing or two. And to that point, I would also mention that conceptually, most of this tutorial applies to any native, compiled language.

For widest applicability, this tutorial will feature GNU tools (GCC) used in a Unix-like environment (POSIX). For Mac OSX, the preferred compiler is Clang++, which involves a tool-suite compatible with GNU tools. Similarly, under Windows, the MinGW tools (incl. GCC) are also mostly the same, with some special issues. The only drastically different environment is the Microsoft Visual C++ compiler (MSVC). The oddities of the MSVC stack is beyond the scope of this tutorial.

Glossary

Before we start, we have to explain a few of the terms we will encounter:

Header file: Contains C++ source code and they are mostly used to make declarations, i.e., they contain the stubs that tell the compiler about the "things" that exists (somewhere). Usual extensions: .hpp, .h, or .hxx.

Source file: Contains C++ source code and they are exclusively used for definitions, i.e., the actual implementation of the "things" that make up the program or library. Usual extensions: .cpp, .C, or .cxx (normally, .c is reserved for C source files, not C++).

Translation unit (TU): A …

DeanMSands3 commented: Bookmarked! +5
Labdabeta commented: Excellent, as usual! +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

what is the chrono type for use these big number?

That is none of your concern, nor is it mine. Chrono (like even the old time libraries) is designed to hide away all this nonesense about what type is actually used under-the-hood to store the time values. I don't know, and I don't care, and neither should you.

The kind of conversions that you are trying to do is already provided by the chrono library, and you should not attempt to do them yourself (in part, because of the possibly large numbers involved).

First of all, the chrono library has a number of "duration" times to represent various units, and they all inter-operate very well. And if you need to do a conversion, you can use the duration_cast function. So, your loop that tries to wait 5 seconds can be written like this:

#include <iostream>
#include <chrono>

using namespace std;

int main()
{
    auto start = chrono::high_resolution_clock::now();
    auto end = chrono::high_resolution_clock::now();
    auto interval = chrono::seconds(5);

    while ((end - start) <= interval)
    {
        end = chrono::high_resolution_clock::now();
    }

    // here is the part where I do a cast:
    auto total_ms = chrono::duration_cast< chrono::milliseconds >(end - start);
    cout << "The time elapsed was " << total_ms.count() << " ms." << endl;

    cin.get();
}

The chrono library uses a number of different types under-the-hood, but mainly you should know that some are time-points (time_point) and some are durations (duration). Their internal representations and whatever else is none of your concern, …

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

Digging a bit deeper, it seems that the reliability of QueryPerformanceCounter or the Linux equivalent isn't really much of a problem anymore. The whole issue had to do with multi-cores keeping separate counters and the introduction of cores that can slow down, thus, slowing the progress of the counters. Both Intel and AMD processors have had counter-measures (constant_tsc and hpet / lapic interrupts for sync'ing) for almost a decade now. So, there is really only a small window of PCs that have those features (multi-core / variable-speed) and that are, at the same time, too old to have the counter-measures. It seems like only "fancy" PCs from 2001-2005 or so might be susceptible to this problem (the list is short). I think it's one of these issues that has a life of its own, it was a short-lived concern at one point, but isn't anymore. It was only an issue with pre-Vista Windows high-end PCs from the early 2000s.

As I said earlier, you shouldn't expect the QueryPerformanceCounter or Linux equivalent to be reliable down to the "advertised" resolution of 1 nano-second. But, today, it's perfectly reasonable to expect reliability down to 1 micro-second or so. That is, unless you run a deprecated operating system (pre-Vista Windows) on a deprecated machine (about 10 years old).

sorry.. i'm confuse... so 1 000 000 it's 1ms?

Yes, it is:

1 milli-second (ms)  = 1,000 micro-seconds (us)  = 1,000,000 nano-seconds (ns)

And the scale of the high_resolution_clock durations is …