Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

876 Good

About NotAYakk

  • Rank
  1. mt probably means multi threaded. However, none of the above are library problems -- library problems would happen at link time, not compile time. You can configure MSVC to dump out what header files it is including, and the chain. I forgot what exact verbose setting it is. Use it, and make sure that the header files you are including are the header files you want to be including. Do you have more than one copy of boost installed? How, exactly, did you install it? Is that hpp file a public interface of boost date time, or an internal header file?
  2. Quote:Well, I think that it's entirely reasonable for a failed stream or iterator operation to throw an exception. If I were to exit gracefully instead of propagating the client's exception, I would essentially be exposing an implementation detail - namely the fact that the underlying library is written in C. Well, you could simply state in your guarantees that you throw UnknownException if you don't know the exception, and you throw Foo if the exception if Foo for some limited set of exceptions Foo. This happens to be because you are using a C library -- but the user doesn't have to know _why_ you are making this strange requirement. This is your option #3. But really, #3 is handled by current_exception: Quote:Correct implementation of current_exception may require compiler support, unless enable_current_exception was used at the time the currently handled exception object was passed to throw. If enable_current_exception was not used, and if the compiler does not provide the necessary support, then current_exception may return an exception_ptr that refers to an instance of unknown_exception. In this case, if the original exception object derives from boost::exception, then the boost::exception sub-object of the unknown_exception object is initialized by the boost::exception copy constructor. Ie, if you lack compiler support, current_exception still functions and returns unknown_exception. And, they can use enable_current_exception on their exceptions if they want them to be passed through your code. Even without compiler support. So #2 and #3 reduce to using boost::current_exception. It degrades nicely! (or it claims to!) Generally, I'd avoid #1. C code is not supposed to deal with exceptions. People maintaining C code don't test if they allow exceptions to pass through. It will add a pair of different cases to your C++ code, which doubles the unit test surface area -- and worse than that practically (because you end up testing it against one particular C version of the libraries, and might hide undefined behaviour when you are engaging in undefined behaviour...)
  3. boost convenience magic is standard boost behaviour. :) I'm guessing that their default boost::hash<T> calls size_t hash_value<T>(T const&), allowing the type to be implicitly determined. By overriding hash_value before instantiating the hash<T> class, you make it see hash_value(MyType const&) as being a better hit than hash_value<MyType>(MyType const&)? But this is a guess.
  4. NotAYakk

    Fastest way to intersect Sets

    What is the scale of the problem? This problem: Z = { 1,2,3,4,5 } A = { 6,4,7,9 } B = { 10,1,9,7,8 } C = { 99,1002,33,4 } D = { 243,233,44,5 } is tiny in size. How sparse are your values? Algorithms for sparse values are very different than algorithms for dense values. By fast, are we talking per-pixel fast, per-frame fast, ui-response fast, network-latency fast, level-loading fast, what? For a larger cases (and sparse) of the above, I'd be tempted to use tries, and do intersection there, instead of arrays. Say a 32 bit radix. Have bit-masks for "does contain" and an array of 32 pointers (possibly null).
  5. NotAYakk

    boost::spirit match leading text

    Wait, you said that crashes? Stack trace? ... Do you have any structure in what you want to match? 'row0/col0/flight0_0.flt' Ie, will it look like: ( Word >> / )* >> flight >> digit(s) >> _ >> digit(s) >> .flt? I'd write it like: match = FlightExpression[confirm(temp, result)] | ( Word[failure(temp)] >> "/" >> match ); FlightExpression = "flight" >> Digits >> "_" >> Digits >> ".flt" >> end_p; Digits = int_p[push_back_a(temp)]; Word = *(~chr_p('/')); Note that 'false positives' could appear while parsing. confirm is a functor that takes the data in temp, and stuff it into result. failure is a functor that clears the data in temp. I played fast and loose with spirit syntax above (I left at least one str_p() constructor out that you would need to include). Note, I'm not a boost::spirit expert. Finally, the above will fail to match abcflight2_3.flt which might not be what you want. To match abcflight2_3.flt, I'd drop the '/' delimeter, and say that Words are character sequences that start with an arbitrary character, followed by any number of non-'f' characters. This will make your engine try a "FlightExpression" match whenever there is an f, and on failure consume that f (and any non-f characters) and try again at the next f. But that might be too generous. :) To craft the above, I'm using implementation details on how parsers like spirit operate. They try to match the earliest of a given set of alternatives, and do each match greedily.
  6. NotAYakk

    Problems with pointers

    So, let's talk about memory in a computer. I'll be making things simple. There are two kinds of memory, as far as C++ is concerned. There is stack memory, and heap memory. Stack memory is stuff like variables. Heap memory is ... well, most everything else. Heap Memory is like a long roll of paper. On the paper is written a bunch of numbers. As it happens, you can take this roll of paper, and quickly find the 1027th entry in it. So each of the entries in Heap Memory is referred to by where it is in the order -- we call this the address of the entry into Heap Memory. Stack memory you could think of as your 'scratch work' for solving a problem -- a small amount of area you can write on for temporary work. Each of these also has an address, just like Heap Memory (to make your mind boggle, we actually store the Stack Memory in the same long roll of paper as the Heap -- we just manage it differently). A pointer is just the address of some information in memory. So when you did this: cout << myIntegerPointer; you sent to cout the address that your pointer is. This was 0031blahblah -- a pretty big number, because that roll of memory I talked about is _really long_. These addresses are very much like street addresses, written down somewhere. Instead of thinking of an offset into that huge roll of paper I called "Heap Memory", you could think of it is a street address on a really really long street. In C/C++, we have an idiom to take the address of memory. We take the expression that represents the value, and we stick a & in front of it. You did that in your bit of code -- int *myIntegerPointer = &i; -- and you took the address of i, and stored it in myIntegerPointer. The reverse of that & operator, in C/C++, is the * operator. (Yes, that is the same operator used for multiplication!). So to look up the value of the thing that is stored where myIntegerPointer is referring to, you type: *myIntegerPointer If you want to print this out to the screen, you'd do: cout << *myIntegerPointer; As an aside, see the int* myIntegerPointer = &i? If you move the * over a bit, you get this: int *myIntegerPointer there is a way to remember how to use pointers right above. If you write the expression *myIntegerPointer, you get ... an int. And yes, that is intentional -- that is why they used that particular way of expressing the type of pointers and how to 'dereference' a pointer. Does that make sense?
  7. NotAYakk

    C#-esque properties in C++?

    The goal is to have a member variable that 'acts like' a member variable of type T, but when read or written from, arbitrary code is run. Ideally the arbitrary code will be syntactically easy to deal with. C++ doesn't support this perfectly. It can get pretty close if you pretend your class has a pointer-to-data instead of instance-of-data in the syntactic sugar sense (ie, require *foo.bar += 7 instead of foo.bar += 7), as that gives you consistent operator-> behaviour. Hmm. What if the pattern we followed was that of an iterator, but we didn't have operator++ and the like. There still is the problem of dealing with the copy constructor of the class that owns us. Ie: struct A { Property<int> foo: }; int main(int, char const*const*) { A a; A b; a = b; a.foo = 6; } Operator= on Property<int> has to behave very non-iterator/pointer like -- more like a reference. Even then, you can imagine a Property with a 'back end' store ending up behaving very badly. This is an artefact of mixing reference (which the Property has) and pointer (which the 'back end' store might have) in the same class, and it causing very unexpected behaviour.
  8. NotAYakk

    C#-esque properties in C++?

    I'd rather my properties have the signature: template&lt;typename T&gt; class Property { private: typedef boost::function1&lt; void, T const& &gt; setter; setter set; typedef boost::function0&lt; T &gt; getter; getter get; public: Property( setter set_, getter get_ ); operator T() { return get(); } void swap( Property& other ); void swap( T& other ); Property& operator=( T const& src ) { set(src); return *this; } Property& operator+=( T const& src ) { T tmp = get(); tmp += src; return (*this)=tmp; } T operator+( T const& src ) const { T tmp = *this; tmp += src; return tmp; } [...] }; with the 'stored value' property: template<typename T> void StoredValueProperty: public Property<T> { [...] }; that has a reference to the data, and marshalls functions that take a reference to T& and turns them into valid set/get functions for Property<T>, and: template<typename T> void HasValueProperty: public StoredValueProperty<T> { private: T t; [...] }; which actually owns the T for you. And yes, this won't be nearly perfectly efficient. But you are wanting to emulate a C# feature, so you really cannot expect it to be that efficient. The Property code with all of those invalid overrides uses the feature of C++ that a template class's methods don't get validated unless called. So even if you have a string property for which += makes no sense, so long as nobody calls += your code is fine. Once they call +=, they get a compiler error at that point. All of this is quite doable. [Edited by - NotAYakk on July 6, 2009 2:44:32 PM]
  9. NotAYakk


    To reduce he amount of work that you want others to do, write a pure function that reproduces your problem. Your original code that had a problem: void Level_Change_Subject::Notify_Listeners_Intermission(Level& level, const Point& entry_point) { std::for_each(listeners.begin(), listeners.end(), boost::bind(&Level_Change_Listener::Notify_Intermission, _1, level, entry_point)); } Change it to this (where you fill in the [...] parts): class Level_Change_Listener { public: virtual ~Level_Change_Listener() {} // Be notified that the level change has started. virtual void Notify_Started() = 0; // The level has given us permission to do any loading etc. we require. // entry_point is the position of the player in new_level. virtual void Notify_Intermission(Level& new_level, const Point& entry_point) = 0; // Be notified that the level change has finished. virtual void Notify_Finished() = 0; }; typedef [...] Level; typedef [...] Point; typedef std::vector<Level_Change_Listener> Listeners; // or whatever type your container is void Do_Notify_Listeners_1( Listeners& listenders, Level& level, const Point& entry_point ) { std::for_each(listeners.begin(), listeners.end(), boost::bind(&Level_Change_Listener::Notify_Intermission, _1, level, entry_point)); } The goal of the above is that it reduces your problem down to a byte-sized snack. You could then start breaking your code down into smaller steps: void Do_Notify_Listeners_2( Listeners& listenders, Level& level, const Point& entry_point ) { for(Listenders::iterator it = listeners.begin(), it != listeners.end(); ++it) { Level_Change_Listener* listener = *it; boost::function1< void, Level_Change_Listener& > func = boost::bind(&Level_Change_Listener::Notify_Intermission, _1, level, entry_point); func(*listener); } } and finding out where the problem happens (or stops happening). In any case, in spending too much time working on your problem, I found an answer I think: When calling boost::bind, change level to boost::ref(level), and entry_point to boost::cref(entry_point) -- I think that might fix your problem.
  10. (B::A)(*this) . foo (); // Line 21 (C::A)(*this) . foo (); // Line 22 That is bad mojo. You are taking your *this, and casting it to a distinct instance of B::A. Code that isn't bad mojo yet is similar in flow would be: (B*)(this)->foo(); (C*)(this)->foo(); with the note that using C-style casts is massive overkill and should be avoided. As in this case you can do it implicitly, do it -- see SiCrane's post. Note that SiCrane's post has a formatting bug -- the forum ate the template arguments to the static_casts (where where A* I'm guessing).
  11. NotAYakk

    A little C++ quiz

    Quote:1. What is the type of "hello world"? This is only useful if you are looking at strange debugger errors, or doing implicit template typing during a function call. So not that useful. Quote:2. List the differences between call-by-value and call-by-reference-to-const. I'd have the two signatures listed. Quote:3. Why is the following code ill-formed? int* a = new int[100]; delete a; I'd ask 'what bugs be likely to occur in the following code?', and if you are pedantic 'what guarantees about the code does the standard provide?' In particular, with many implementations of the standard library, the above code may be ill-formed, but still work. Code that looks much like it, meanwhile, will be horribly broken. And naturally, a compiler revision could take your 'works' version of the code and break it horribly, as it relies on non-standard behaviour, if I remember rightly. Quote:4. Explain "Resource Aquisition Is Initialization". If you are going to use buzz words, why not just call it RAII? :p It is possible that they know what this is, but don't know the name. Not likely, I suppose, but still... Quote:5. What is the static initialization order fiasco, and how do you circumvent it? Again, here you have the problem of using buzzwords.
  12. NotAYakk

    [C++] Template inheritance

    A better option might be: template<typename Scalar, unsigned int Dimension> struct VectorBase { // here you have the non-specialised base operators }; template<typename Scalar, unsigned int Dimension> struct Vector: VectorBase<Scalar, Dimension> { // Here you implement some default Vector constructors/operators // That don't get inherited from VectorBase. }; template<typename Scalar> struct Vector<Scalar, 3>: public VectorBase< Scalar, 3 > { // here you implement the Vector3 methods // x(), y(), z() etc. // By using specialisation instead of a new class, // these methods 'happen for free'. }; Having both Vector3<int> and Vector<int, 3> seems like overkill. ... If you want to go really crazy, you could even go as far as to support Vector< Vector<int, 3>, 3>. Is there any way you could support Vector< int[7][3] >?
  13. NotAYakk

    Design Patterns Advice

    struct MenuItem { virtual void handle() = 0; virtual std::string name() const = 0; virtual ~MenuItem() {} }; struct Menu: MenuItem { std::vector<MenuItem*> items; std::string menuName; Menu( std::string, std::vector<MenuItem*> const& ); std::string name() const { return menuName; } bool validate(int choice) { if (choice < 0) return false; if (choice >= (int)items.size()) return false; return true; } void printMenu() { std::cout << "<" << name() << ">\n"; for(int i = 0; i < (int)items.size(); ++i) { std::cout << i << ") " << items->name() << "\n"; } } void handle() { while(true) { printMenu(); int option = getInput(); if (!validate(option)) { std::cout << "Invalid option\n"; continue; } items[option]->handle(); return; } } }; This is the similar-level data-driven version of the menu code. It can be written much better. Depending on your platform, being able to have your menu be configured without touching C/C++ code can be a serious advantage. In other situations, this might be moot.
  14. "Without using new memory" is almost certainly about "without using O(n) new memory". Unless they want ASM for a particular CPU, because C/C++ doesn't give memory guarantees +that+ tight!
  15. NotAYakk

    Design Patterns Advice

    Write your menu to contain an arbitrary number of options. The view of the menu (the one that says "pick one of the following: 1: foo, 2: bar, ...") gets the user input. It then determines which menu to use (possibly using a std::vector<> look-up), and depending on the data in that menu item, does something. Maybe it calls a function in the menu item that determines what happens. Maybe it displays a sub-menu based off data in that menu item. This is classic model/view stuff, with maybe a dash of flyweight. Another consideration is that you might not want your menu to be 'stack based'. Ie, if a menu item says "run X", it doesn't run it in the current context, but rather has it set up the running of X to happen. If you have a stack of menus, store the explicitly instead of implicitly in the execution stack, so you can manipulate it. By this point I'm probably beyond what you need for your particular project.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!