Jump to content
  • Advertisement

CapThunderNutz

Member
  • Content Count

    13
  • Joined

  • Last visited

Community Reputation

194 Neutral

About CapThunderNutz

  • Rank
    Member
  1. CapThunderNutz

    C++11 template question

    I can debate you on all these points but after trying to insert an image to prove my A* claim below, I accidentally lost everything I've typed :S   Please don't think that I'm just arguing for the sake of arguing or intentionally trying to rub people the wrong way. I have to talk about my experiences because I would just be lying talking about anything else. The reality is I disagree with you on almost every-point. My background is in firmware development and consequently I have done everything from writing compiler, compiler patches (where gcc generated incorrect assembly for an MSP4530) to full pre-emptive operating systems, custom schedulers, etc. I think you put too much faith in your compiler. They are written by very clever people, but compilers are only as smart as the people who write them.   You want your debug code to be similar enough to your release code so you can debug with confidence knowing that an issue in release mode can be debugged. The reality in embedded development is that when code paths change can experience everything from stack overflows to silicon errors (that required particular asm sequences that the compiler optimised out), etc. If your relative timing changes, then you may or may not be able to debug timing issues on your interfaces and you will see that with multi threaded applications where race conditions exist in one mode but not the other etc. The reality is, the closer your debug version is to your release version, the better you life is regarding debugging. I have seen cases where problems has been so severe that the debug version was actually the version that was shipped. Debugging programs take time, like everything else on the project, it's not adequate to disregard it as having no impact on the final product.   Your function call overhead in debug mode could very well be the reason between a race condition appearing or disappearing. Runtime vs compile time penalties are massively important. About 6 months, my friend and I wrote two separate implementations of the A* star algorithm, using the pseudo code published on wikipedia. Like you he believes very much templates and not using "clever little tricks" and well I obviously don't. He used all the respective STL and C++ functions he thought appropriate and I implemented my own containers using core C++ with general firmware best practices. In the end, for the same path using the same heuristic, mine was on average 1000x faster. Using a slightly modified heuristic mine became 2000x faster. (Respective calc times: 0.393397 seconds vs 975.823250 seconds.) I was going to write it up as an article to post here, but I have to admit, I'm a bit worried now. Both bits of code has been build with purely macro optimisations (i.e. which data structure is the best for the job, etc, no ASM, SSE, etc) and what ever default optimisation were provided for release mode builds.   You may not agree with me and I respect that. But for me game engines are closer to firmware (realtime) than a desktop processing application (non-realtime). As such, I don't want surprises and I certainly want performance. Any time that my engine wastes is time that the game developer cannot use adding extra awesome.   This conversation is starting to sound exactly like the same flame wars that rage on the kernel formus any time someone mention C vs C++ for kernels, etc. As such, I will respectfully opt out of any further discussion on this thread.
  2. CapThunderNutz

    C++11 template question

    With a caveat. There is no run time penalty when compiled in release mode. It will be different in debug mode because of how the code is generated. In a test of performance difference, it showed the template to be 10.3 (1031%) times slower than the #define. When compiled with optimisation, the template speed increased by 7450% and the #define by 724%. (This test was performed with 10 000 000 000 lookups in 100 batches). Well no. In debug builds I would expect it to be treated as a function and in release build as a constant. This has different effects on your stack, status registers, etc. The template is fundamentally different depending on the compile mode. Yes there is that as well, but they do it because it works, what you see is what you get and it is reliable. The instance you let the compiler decide, you have to hope for the best (especially if you are moving across platforms). You have to admit, the dirty little #define is a lot more consistent.
  3. I think this should do it for you: Load the image data (perhaps use something like libmagic). Create an image using XCreateImage. Create an off-screen pixel map using XCreatePixmap. Put the image in the pixel map using XPutImage. Paint the image onto the window using XCopyArea on all expose events. I did the same thing a while back from something base on a solution I read on stackoverflow. Luckily I save the link the code comments. http://stackoverflow.com/questions/6609281/how-to-draw-an-image-from-file-on-window-with-xlib    Hope it helps.
  4. I think you perhaps have two options here.   The first thing you can try is to change the the type to an integer, I would only expect doubles or floats to be treated in this way. (This should remove the e+ notation.) I.e. is it a timestamps in milliseconds since the Epoch?   The second thing would be to look at the API interface for writer a bit closer and possibly the writer.cpp source. I haven't had any direct experience with json-cpp, but out of curiosity looked at the source real quick, seems like it outputs to an ostream object. Not sure if you can supply the ostream or not, but it suggests that you may be able to set the output formatting on the ostream object.   For example, this code: double testNum = 12323541245634262.0; std::cout << "Number: " << testNum << std::endl; will print:   Number: 1.23235e+016   However, this code: double testNum = 12323541245634262.0; std::cout << std::fixed << std::showpoint; std::cout << std::setprecision(4); std::cout << "Number: " << testNum << std::endl; will print:   Number: 12323541245634262.0000   If you have access to a writer function or constructor that accepts an ostream object, you can create your file like this: std::ofstream ofs ("test.json", std::ofstream::out); ofs << std::fixed << std::showpoint; ofs << std::setprecision(4); Hope it helps.
  5. CapThunderNutz

    C++11 template question

    The basic parameter to the function says that you are passing in a reference to an unnamed array (the (&) part), which is of type T (the T part) and of size N (the [N] part). Since this information must be known at compile time, it means it only work for explicitly declared arrays that will never change size, i.e. something like int temp[50], however if you did something like pass the array in as a pointer, you loose the size information of the array and the code wont even compile. Thus in summary the value of N is derived from the size used in the array declaration.   This example shows the case where it works because the size (which is 50) of the array is known at compile time: #include <iostream> template<typename T, std::size_t N> constexpr std::size_t arraySize(T (&)[N]) noexcept { return N; // and } int main() { int temp[50]; std::cout << "Array Size: " << arraySize(temp) << std::endl; return 0; } This shows a broken example where the code wont compile because the size information has been lost as the pointer only stores the memory locations of the first element in the array and nothing relating to the size of the array. #include <iostream> template<typename T, std::size_t N> constexpr std::size_t arraySize(T (&)[N]) noexcept { return N; // and } int main() { int temp[50]; int * temp1 = temp; std::cout << "Array Size: " << arraySize(temp1) << std::endl; return 0; } The function parameter don't have to be unnamed, i.e. it can be given a name though there is no point since it's not referenced inside the function. I.e: template<typename T, std::size_t N> constexpr std::size_t arraySize(T (&array)[N]) noexcept { return N; // and } And for good measure, since I rarely see arrays being passed in by reference, here is a short example of passing arrays by reference to functions. #include <iostream> // The size of the array. #define ARRAY_SIZE 50 // Return the size of the array. template<typename T, std::size_t N> constexpr std::size_t gArraySize(T (&)[N]) noexcept { return N; } // Print the content of an array. void gPrintArray(int (&temp)[ARRAY_SIZE]) { // Print all the values. for(auto i : temp) { std::cout << i << ","; } // Output a new line. std::cout << std::endl; } int main() { // The temporary test array. int temp[ARRAY_SIZE]; // Initialise the array. for(int i = 0; i < ARRAY_SIZE; i++) { // Set the array value to it's index in the array. temp[i] = i; } // Print the size of the array. std::cout << "Array Size: " << gArraySize(temp) << std::endl; // Print the array. gPrintArray(temp); return 0; } Of course, those of us who write firmware will not go through all this trouble just to get the size, we just straight use the ARRAY_SIZE definition to save precious clock cycles ;)
  6. CapThunderNutz

    (64 bit)Cross Platform GUI with OpenGL Support?

    QT is amazing for making cross platform game editors (which seems to be similar to what you are wanting to do?). I use it all the time, mind you I have not moved to QT5 yet, still in QT4. QT is a very refined GUI library and is very portable, well worth the time to learn it.   *EDIT*   After ocornut's post, I feel like I should probably explain more why my preference is for QT. I imagine it is a bit subjective so it's probably worth saying I've been using QT since 2010, and these are my experiences: If you are developing for Windows, Linux and OSX, it works with minimal effort. It is a mature and very stable GUI library with many years of development behind it. A massive amount of documentation readily available both on-line and with the downloadable SDK. Many working examples that ship with the SDK. It appears to have a very large user bases. Support advanced concepts like Model-View-Controllers, asynchronous jobs, etc. Have a lot of common classes like QSettings for loading / storing application settings, Image Manipulation, CSS like style sheets, XML, OpenGL, SQL, Unit Testing , etc. The QT Creator IDE runs on WIndows, Linux and OSX and is surprisingly good. I have completely moved away from VS, Vim, etc and now just QT Creator for all my C/C++ needs. Integrates well with build systems like CMake. Very nice GUI build that ships with QT Creator and it is very easy to create custom widgets.
  7. CapThunderNutz

    Member function pointers?

      Haha that is such a dodgy trick, I love it. :)   For those reading and wondering what is going on, this only works because the stack is being corrupted just right by the non-member function (f) passing in the object instances as the transparent "this pointer" parameter. Absolutely not the sort of thing you do for production code ... unless you are writing an OS without context switching registers or similar. Definitely a no go for user space code. 
  8. CapThunderNutz

    Member function pointers?

      For type correctness it needs to include AnotherClass as the type definition.   START - HORRIBLE CODE (I only show this for learning purposes, don't actually do this)   Of course, C++ allows you to be evil by letting you cast everything into everything else. I suspect how you go with this will vary from compiler to compiler, and if you treat warnings as errors, then I suspect the code will not compile anywhere. If you were to directly cast it as shown below and execute the function, I'm not sure exactly what will happen, but I strongly suspect it would be deemed unknown behaviour.  void (*MyFunctionPtr)() = (void (*)())(&TestClass::MyFunction); MyFunctionPtr(); Now if you slightly modify this code to look like the snippet below it will work if you get the address from the object instance directly, but it basically ignores the standard and has the same problems of what will the compiler actually do. I would not recommend you do this any any production code. (Note for this code to compile, you need to specify the -fpermissive compiler option for g++ and mingw.) I don't know if this works in either Clang or Visual Studio. void (*MyFunctionPtr)() = (void (*)())(&testObject.MyFunction); MyFunctionPtr(); END - HORRIBLE CODE     The previous examples that I showed will work for either Classes or Structs. In C++ there are only two differences between structs and classes. This link explains it well: http://stackoverflow.com/questions/92859/what-are-the-differences-between-struct-and-class-in-c.        I'm not sure what you mean by pure. If you keep it in C++ land, then you don't need to change anything. If you go to C land, then the concept of classes don't exist. The cleanest way you can do that will be to be to create a wrapper type (or use stl::function) that is cast to a void pointer for storage in you C struct. If you then need to execute the code function pointer, you will need a function in C++ land that will cast the pointer back to the correct type and subsequently invoke the function call.   If this is really what you want to do, I would recommend you look at perhaps other design patterns, or do message / event passing between C and C++ code blocks.
  9. CapThunderNutz

    Member function pointers?

    Ah, no dramas, cheers. I was worried I've done something wrong that I did not understand :P
  10. CapThunderNutz

    Member function pointers?

    Also may I ask (I'm new here and not to clear on the procedure regarding down votes) why post #5 was voted down? I actually compiled the code in post #4 and could not get it working without changing the second parameter to an instance of TestObject. I can only think that it was because I put it as a new instance inside the function call where it most certainly will create a memory leak, but since none of the examples are technically complete with a lot of implied error / exception checking and assumed functionality, I fail see why this would be a particular problem for any C++ programmer.
  11. CapThunderNutz

    Member function pointers?

    It's all about how functions are stored. There is a lot of information on the internet about this, so I wont repeat it here, i.e. see: http://stackoverflow.com/questions/15572411/where-are-member-functions-stored-for-an-object But the short and sweet of it, that if you want to store a pointer to a member function you need two bits of information. The pointer to the function that will be invoked, and the instance (this pointer) of the object that will be passed to the member function as a transparent parameter.   Non-Member functions and Static functions don't need a transparent parameter to be passed since the live in a different world where they are unique so you only need to know the pointer to the function.   The STL functions that others have posted basically wrap all this up for you. For the sake of learning I've used raw C++ (with the exception of "iostream" to give the function something testable to do) only I've implemented your original example. (I changed AnotherObject to AnotherClass, because Objects are instances of Classes ... a little bit pedantic, sorry ). It is implemented using three code files, copy, paste and experiment.   File: AnotherClass.hpp #ifndef ANOTHER_CLASS #define ANOTHER_CLASS #include "TestClass.hpp" class TestClass; class AnotherClass { public: // The pointer to the TestClass object on which the pointer must be // initialised. TestClass * fTestObjPtr; // The function pointer to the TestClass member function that will be // invoked. void (TestClass::*fMyFunctionPtr)(); // This function invokes the external function. void InvokeFuncPtr() { (fTestObjPtr->*fMyFunctionPtr)(); } }; #endif // ANOTHER_CLASS File: TestClass.hpp #ifndef TEST_CLASS #define TEST_CLASS #include "AnotherClass.hpp" class TestClass { public: void Init(AnotherClass * anotherObject) { // Set the object to invoke on. anotherObject->fTestObjPtr = (TestClass*)(this); // Set the function pointer to invoke. anotherObject->fMyFunctionPtr = &TestClass::MyFunction; } // The function to be invoked by Another Class. void MyFunction() { std::cout << "Hello there!" << std::endl; } }; #endif // TEST_CLASS File: Main.cpp #include <iostream> #include "TestClass.hpp" #include "AnotherClass.hpp" int main() { // Create the test object. TestClass testObject; // Create the another object. AnotherClass anotherObject; // Initialise the test object. testObject.Init(&anotherObject); // Execute the function. anotherObject.InvokeFuncPtr(); return 0; }
  12. CapThunderNutz

    Member function pointers?

    Streway, you need to change the line: ao.callback = std::bind(&TestObject::MyFunction, &ao);  to ao.callback = std::bind(&TestObject::MyFunction, new TestObject()); (or to another instance of the TestObject).
  13. CapThunderNutz

    Member function pointers?

    You need two bits of information:   The address of the member function within the class. You get this directly using the class definitions. The instance of the object whose member function you want to invoke. A fully working example is shown below, copy and paste it to experiment. #include <iostream> class A { public: float Multiply(float x, float y) { return x * y; } }; int main() { // 1. Get the address of the member function inside the class. float (A::*functPtr)(float, float) = &A::Multiply; // 2. The instance of the object whose member function you want to invoke. A * objPtr = new A(); // 3. Invoke the function pointer on the object instance. std::cout << "2 x 3 = " << (objPtr->*functPtr)(2.0f, 3.0f) << std::endl; return 0; }
  • 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!