|
User0015 posted:If anyone was up for it, I had some questions I'd like to ask via e-mail. That, or start my own thread. I don't think a thread really warrants my questions, since they'd mostly be single question/comment types. If only there were a thread specifically dedicated to (C++) questions not worth their own thread...
|
# ? Nov 24, 2008 22:11 |
|
|
# ? May 18, 2024 08:34 |
|
Painless posted:Does anyone know what's going on with std::sort? Is it just that GCC 3.4.4 and visual c++ express suck at optimizing, or am I doing something wrong here? You're comparing apples and oranges; your comparison function (which is wrong, by the way) is not the same as std::greater<int>. I don't know if that's the only factor, but it's the most glaring one.
|
# ? Nov 24, 2008 22:13 |
|
Avenging Dentist posted:Real men use Boost.Spirit and write an EBNF grammar to parse the morse code. This actually looks pretty awesome and I'd love to use it but I can't seem to find any really short examples of parsing something and actually doing anything with it aside from confirming that yes, a string does indeed fit an EBNF. Can you point me towards a simple example or write something that would parse and evaluate: code:
|
# ? Nov 24, 2008 22:22 |
|
floWenoL posted:If only there were a thread specifically dedicated to (C++) questions not worth their own thread... To be blunt, part of the reason I'd prefer e-mail is to avoid responses like these.
|
# ? Nov 24, 2008 22:25 |
|
floWenoL posted:You're comparing apples and oranges; your comparison function (which is wrong, by the way) is not the same as std::greater<int>. Oh heh, you're right. Fixing the comparison function makes qsort go about 2.5 times slower.
|
# ? Nov 24, 2008 22:27 |
|
User0015 posted:If anyone was up for it, I had some questions I'd like to ask via e-mail. That, or start my own thread. I don't think a thread really warrants my questions, since they'd mostly be single question/comment types. ok, feel free to email me at hexadecimal12f0af9@gmail.com
|
# ? Nov 24, 2008 22:28 |
|
Contero posted:This actually looks pretty awesome and I'd love to use it but I can't seem to find any really short examples of parsing something and actually doing anything with it aside from confirming that yes, a string does indeed fit an EBNF. Can you point me towards a simple example or write something that would parse and evaluate: I am also interested in this.
|
# ? Nov 24, 2008 22:29 |
|
floWenoL posted:You're comparing apples and oranges; your comparison function (which is wrong, by the way) is not the same as std::greater<int>. Counting calls to rand in the performance test probably doesn't help either, since it obscures the actual amount of time spent sorting. That said, I ran it on my machine and got the following in MSVC8 with O2: qsort: 1.594s std::sort: 1.313s And on a Linux VM with GCC 4.3.2 and -O3: qsort: 2.39s std::sort: 0.89s Oh, also: you need to include <functional> if you want to use std::greater.
|
# ? Nov 24, 2008 22:36 |
|
Painless posted:Using MinGW (-O3), the qsort part goes much (about three times) faster than the std::sort part, which is completely unintuitive. Ok, I thought, it might be doing some weird special processing for qsort, let's move the compare_desc function to a different file. Doing this made the qsort version go about two times slower, so obviously some special processing is going on. In Visual C++ express, the qsort version goes at about the same speed as in MinGW, but the std::sort version is about 1.5 times slower. One thing to note is that on Windows clock() is wall time, but on Linux clock() is proc time. So your results may be a little funny because of that. I'm not 100% on what kind of time clock() on MinGW will return, but that's something to check. FWIW compiling that program but replacing clock() with gettimeofday() on a *NIX system shows qsort() being half as fast as std::sort(). I don't have access to a Windows machine to test on though. As for std::sort() acting differently on different compilers, the STL implementation you use is by default provided by your compiler. So depending on how well your compiler implements std::sort(), you may get varying performance. What you can expect, at least, is that if your STL implementation is standards conforming, that you'll have O(N log(N)) complexity. Edit: Why hello there next page that I totally didn't see till I posted. Lexical Unit fucked around with this message at 22:49 on Nov 24, 2008 |
# ? Nov 24, 2008 22:38 |
|
Language: C I'm trying to create an array of files, which gets filled in a separate function. code:
warning: passing arg 1 of 'fillFiles' from incompatible pointer type I know I'm either declaring file improperly in the first place, or setting the parameter in fillFiles improperly, but no combination of asterisks and/or brackets have come out successful so far. I would also like to understand what I'm doing wrong rather than just trying out different combinations in hopes of getting lucky.
|
# ? Nov 24, 2008 23:09 |
|
Contero posted:This actually looks pretty awesome and I'd love to use it but I can't seem to find any really short examples of parsing something and actually doing anything with it aside from confirming that yes, a string does indeed fit an EBNF. Can you point me towards a simple example or write something that would parse and evaluate: Here's the shortest example I can think of. Note that this isn't how you'd write a large parser in Spirit (the docs show more about that). Also note that Spirit is top-down and so left-recursion is not allowed. http://paste.ifies.org/166
|
# ? Nov 24, 2008 23:14 |
|
Nahrix posted:I know I'm either declaring file improperly in the first place, or setting the parameter in fillFiles improperly, but no combination of asterisks and/or brackets have come out successful so far. I would also like to understand what I'm doing wrong rather than just trying out different combinations in hopes of getting lucky. file is an array of length 10 of FILE* (i.e. FILE*[10]). Therefore &file will be a pointer to an array of length 10 of FILE* (i.e. FILE*(*)[10]), which won't match the argument type, hence type failure. However, values of array type can "decay" automatically to values of pointer type; hence file can decay to a FILE**, which is exactly what you want.
|
# ? Nov 24, 2008 23:48 |
|
rjmccall posted:hence file can decay to a FILE**, which is exactly what you want. But I'm using FILE** as a parameter already.
|
# ? Nov 24, 2008 23:57 |
|
Nahrix posted:But I'm using FILE** as a parameter already. the expression "file" is of type FILE** (or decays to it) so adding &file is of type FILE***, and you're trying to pass it to a function which takes FILE**.
|
# ? Nov 25, 2008 00:02 |
|
Nahrix posted:But I'm using FILE** as a parameter already. He basically wrote a lot of words to say "call with file and not &file".
|
# ? Nov 25, 2008 00:02 |
|
Avenging Dentist posted:Besides that, your #define obscures compiler errors, behaves differently from the C++0x range-for standard, and uses post-increment on the iterator. What's wrong with a post-increment on an iterator?
|
# ? Nov 25, 2008 00:40 |
|
Adhemar posted:What's wrong with a post-increment on an iterator? Post-increment copies the iterator, whether that was desired or not. If iterator copying is complex, there's a chance the compiler might not be able to optimize away the copying. Just in case, it's better to use pre-increment in all cases unless you need the copy.
|
# ? Nov 25, 2008 00:46 |
|
Adhemar posted:What's wrong with a post-increment on an iterator? It creates a temporary needlessly, which may or may not be optimized out.
|
# ? Nov 25, 2008 00:47 |
|
Adhemar posted:What's wrong with a post-increment on an iterator? A lovely compiler (or a decent compiler on a weird/complex iterator type) may create a useless copy if you use postincrement e:floWenoL:argh:
|
# ? Nov 25, 2008 00:48 |
|
Is there any well-known pattern for this situation? Say I have a bunch of classes all deriving from an abstract base. I have an object of type AbstractBase*, and I want to make a copy of it. How do I do this without RTTI and a big ugly switch statement? The solution I came up with is for AbstractBase to have a pure virtual clone() method which each derived class implements as: code:
Clearly it works, but it still seems somewhat inelegant to me since every time I derive a new class from AbstractBase I need to re-implement clone() to do exactly the same thing but with a new type. What I'd really like is for AbstractBase to have basically a virtual copy constructor that would copy-construct the correct derived class when given a const Derived&. Obviously C++ does not support such a thing, but are there any well-known patterns for getting this behavior in an elegant way?
|
# ? Nov 25, 2008 02:44 |
|
Smackbilly posted:Is there any well-known pattern for this situation? i think you can override copy constructor. In your abstract class, there are probably some protected fields, so copy them in AbstractClass copy constructor then in the derived classes call the super constructor and copy the fields that are specific to derived class.
|
# ? Nov 25, 2008 02:52 |
|
hexadecimal posted:i think you can override copy constructor. In your abstract class, there are probably some protected fields, so copy them in AbstractClass copy constructor then in the derived classes call the super constructor and copy the fields that are specific to derived class. This 'solution' is totally broken.
|
# ? Nov 25, 2008 02:58 |
|
hexadecimal posted:i think you can override copy constructor. In your abstract class, there are probably some protected fields, so copy them in AbstractClass copy constructor then in the derived classes call the super constructor and copy the fields that are specific to derived class. That's not the problem, though. If I have a AbstractBase*, I can't know if the pointer is pointing to an object of type DerivedA or DerivedB or DerivedC, so I can't know which copy-constructor to call without using "RTTI and a big ugly switch". Here's a concrete example: code:
|
# ? Nov 25, 2008 02:59 |
|
hexadecimal posted:i think you can override copy constructor. In your abstract class, there are probably some protected fields, so copy them in AbstractClass copy constructor then in the derived classes call the super constructor and copy the fields that are specific to derived class. Copy constructors, being constructors, are by definition non-virtual. That is, if i have a Base *foo = new Sub(); and I call Base(*foo) to copy it, Sub's copy constructor won't get called. Off the top of my head, the easiest solution would be to use CRTP: code:
Avenging Dentist fucked around with this message at 03:10 on Nov 25, 2008 |
# ? Nov 25, 2008 03:02 |
|
Avenging Dentist posted:Off the top of my head, the easiest solution would be to use CRTP: I'm pretty sure that won't work, given the earlier discussion about virtual functions from one superclass 'fulfilling' an abstract virtual function from another superclass. I can't think of a way that avoids having to write clone() for each subclass. Edit: Wait, what about code:
code:
floWenoL fucked around with this message at 03:15 on Nov 25, 2008 |
# ? Nov 25, 2008 03:05 |
|
floWenoL posted:Edit: You mean... what I did but mistyped?
|
# ? Nov 25, 2008 03:11 |
|
I am using g++ 4.3.2 on a 64-bit Linux Machine. When I compile my code with -Wall I get the following two warnings: code:
code:
Any ideas? Is this a bug in g++?
|
# ? Nov 25, 2008 14:11 |
|
The warnings are refering to the first part of the for (;;) head. You are naming the variables, not declaring or assigning to them, and just naming them indeed has no effect.
Vanadium fucked around with this message at 14:31 on Nov 25, 2008 |
# ? Nov 25, 2008 14:25 |
|
Bitruder posted:I am using g++ 4.3.2 on a 64-bit Linux Machine. pElem and pElemParam are already declared, so those statements do nothing. You could either move the initialisation: code:
code:
|
# ? Nov 25, 2008 14:29 |
|
Nahrix posted:
|
# ? Nov 25, 2008 17:49 |
|
How come you can't use a basic string in a conditional statement? Like: code:
|
# ? Nov 25, 2008 22:11 |
|
floWenoL posted:Wait, what about This worked great, thanks. The only annoyance remaining is that I still have to explicitly check the pointer for NULL before I try to clone it, but I can't make C++ do everything for me, I guess.
|
# ? Nov 25, 2008 22:11 |
|
Anunnaki posted:How come you can't use a basic string in a conditional statement? "=" is an assignment. The result of assigning a string to a string is a string, but the conditional statement wants something it can evaluate in a boolean context. You really just want to use "==" here. quote:Also, what's the difference between comparing two strings with an if statement, and using a cstring function, or stringVar.compare? That question does not really make sense. You would use a cstring function or .compare along with an if-statement, not instead of it. The cstring function (strcmp, I guess) is for "C strings", which are just pointers to characters, it does not work on std::strings, much like you cannot call .compare on a C string.
|
# ? Nov 25, 2008 22:14 |
|
Vanadium posted:That question does not really make sense. You would use a cstring function or .compare along with an if-statement, not instead of it. I'm sorry, I meant doing what I did in the example code I posted (if (stringVar1 == stringVar2)), as opposed to .compare, or strcmp.
|
# ? Nov 25, 2008 22:21 |
|
Anunnaki posted:How come you can't use a basic string in a conditional statement? = is assignment, == is equality. When you use a char array or a char pointer (C-style strings), == doesn't compare the underlying string, just whether or not they are stored in the same location, hence why you need strcmp(). std::string (C++-style strings) does what's called "overloading" of the == operator and actually calls a function in the string class that compares the underlying strings. So in the case above, you actually have it correct other than the = vs == mixup (which is a fairly common mistake and I know gcc at least will warn you in case you didn't mean to do that, there ARE times when you want to). C and Java don't have overloading hence why they require a separate function to compare string values. Java DOES have a 'built-in' overload of string concatenation hence why 'name = "John" + " Smith"' works, but C does not, so you need strcat() there.
|
# ? Nov 25, 2008 22:22 |
|
Oh, yeah, you want to use .compare over == if you only want to compare portions of the string.
|
# ? Nov 25, 2008 22:25 |
|
Anunnaki posted:what's the difference between comparing two strings with an if statement, and using a cstring function, or stringVar.compare? As Vanadium said, the functions in cstring are for C-style strings, which are really just raw arrays of characters terminated with a NUL ('\0') character. You really want to avoid using them in C++ code pretty much all the time. C++ has the string class, which is a full-fledge object with useful methods and constructors and overridden operators, etc. If for some reason you really need a C-style string (for example, a system API that was written with C in mind), it is relatively easy to convert between C and C++-style strings: You can pass a C-string to the constructor of a C++ string to make a C++ string with the same value. You can use the C++ string object's assign() method to assign the value of a C-string to a C++ string. You can use the C++ string object's c_str() method to get a const pointer to a C-string with the same value as the C++ string. So even if you have need to use C-strings in C++ code for compatibility reasons, always prefer storing the data as C++ strings and converting to and from C-strings only when necessary. The main comparison functions in cstring are strcmp and strncmp. The latter is the same as the former except it has a max length parameter to account for the fact that a very common bug is for a C-string to lose its NUL byte, which causes the program not to know where the string ends and usually crash (this is the #1 reason not to use C-strings). strcmp/strncmp take two C-strings and returns a negative number, a positive number, or 0. Negative means that the first string is lexicographically before the second, positive means the opposite, and 0 means they are equal. Another caveat is that 0 is equivalent to false in the context of a conditional, so if(strcmp(a,b)) does exactly the opposite of what you might expect it to. Don't use strcmp. With C++ strings, you can just use the normal <, <=, ==, !=, >=, > operators which all behave exactly as you would expect them to. The compare() method in the string class is analogous to strcmp. It returns negative positive or zero with the same meanings as above (be aware again that 0 is false, so if(a.compare(b)) will evaluate to false if and only if they are equal!) The only reason you would usually want to use compare instead of the standard operators is because compare has some overloads that allow you to compare only certain parts of the strings, which could save you a call to substr in some cases.
|
# ? Nov 25, 2008 22:30 |
|
Resurrecting a question from before because I phrased it vaguely and still haven't gotten it right after messing around with it for hours. I'm trying to use the pdcurses library with mingw on windows vista. Can someone tell me how to set it up? I'm not real familiar with this sort of thing.
|
# ? Nov 26, 2008 04:27 |
|
Smackbilly posted:Very informative post. I see, thanks for the post. And yeah, I read about C-string comparisons returning a 0 if they were equal, that kind of confused me (since 0 means false).
|
# ? Nov 26, 2008 06:52 |
|
|
# ? May 18, 2024 08:34 |
|
Anunnaki posted:I see, thanks for the post. And yeah, I read about C-string comparisons returning a 0 if they were equal, that kind of confused me (since 0 means false). Yeah, often you'll see if(!strcmp(...)) used to test for equality of cstrings, sometimes this will be wrapped by an streq() macro or function
|
# ? Nov 26, 2008 07:01 |