Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

815 Good

About JimPrice

  • Rank
    Advanced Member
  1. Yup, in my defence I did put in a comment about vector<bool> having some interesting properties - but given this was a basic introduction to a container class I thought it unlikely it would be a big issue at this time - this code was purely intended as a first glance at containers (without having to worry about the pitfalls of proxy classes). In a larger program I assumed that in fact it would be a vector<int>, or even a vector<shared_ptr<Player> > - although an enum would be good too, I just never use enums enough. Jim.
  2. One solution is an array; however, we're using C++ so we'll use std::vector. Basically this is just a container; we are going to use it to hold the 255 bool values we need to represent our board. Here is some code you can run to see how it all works - it's not 100% "pristine" C++ but you should get the idea :) #include <iostream> #include <vector> // This is our class that is going to handle our game board // We use a std::vector to hold our array and handle indexing ourselves using WhichIndexIsThis class GameBoard { public: // The constructor creates a container with 255 false entries in it GameBoard() : theBoard_(255, false) {} // Attempt to place a piece, returns false is the location is already filled // True otherwise bool PlacePiece(int x, int y) { if(IsSlotFilled(x, y)) return false; theBoard_[WhichIndexIsThis(x, y)] = true; return true; } private: // Query function to check the container of locations bool IsSlotFilled(int x, int y) { return theBoard_[WhichIndexIsThis(x, y)]; } // Turns an x, y location into an index in our container int WhichIndexIsThis(int x, int y) { return 15*x + y; } // A container for our board // False means that square is empty, true means it has a piece played // One thing to bear in mind is vector<bool> has some "interesting" qualities, but it serves our purpose here std::vector<bool> theBoard_; }; int main() { // Create our game board GameBoard theGameBoard; // An ever lasting loop we are going to use until we explicitly break out of it for(;;) { // In practice you'd throw some error checking in here int x, y; std::cout << "Enter an x location (0-14): "; std::cin >> x; if(x < 0 || x > 14) break; // Error check here too! std::cout << "Enter a y location (0-14): "; std::cin >> y; if(y < 0 || y > 14) break; // Check to see if we can place a piece bool result = theGameBoard.PlacePiece(x, y); // This resultant code you might want to have made part of GameBoard class, up to you if(result) std::cout << "Piece placed at " << x << ", " << y; else std::cout << "Location " << x << ", " << y << " already full, try again!"; // Flush for the new loop std::cout << std::endl; } // All done system("pause"); return 0; } Boost probably has an array alternative (probably called something imaginative like boost::array). However, the code above should give you your first steps towards using the C++ libraries container classes. Hope this helps, Jim.
  3. JimPrice

    friend function & template

    The problem lies in that friend templates require explicit statement of the fact they are templates. Hence the following (with some additional comments :) ) // Don't forget to include headers so we can reproduce the example! #include <vector> #include <iostream> using namespace std; // Bleh template<class T> class test { vector<int> v; public: test() : v(10,1) {} // Note the additional syntax making the template statement explicit template <typename T> friend void show_test(test<T>&); }; // Firstly this function shouldn't be a free function; it should be a "Report" member function of test template<class T> void show_test(test<T>& t) { // Firstly tidying up the loop the way you wrote it // How do you know "i" is an unsigned short? for(unsigned short i = 0; i < t.v.size(); ++i) // We are assuming v will be a vector<int>, what if you change the test class and forget to change this? // Take advantage of the nested typedefs // Note that this is a good illustration of why friendship is the strongest relationship classes can have to each other: // for(vector<int>::size_type i = 0; i < t.v.size(); ++i) cout << t.v << " "; cout << endl; // And this is how I would do it, which makes life a lot easier! // However, we are still using the int template variable explicitly - friendship, bleh copy(t.v.begin(), t.v.end(), ostream_iterator<int>(cout, " ")); cout << endl; } int main() { test<int> t; show_test(t); // So sue me, I used system("pause") system("pause"); return 0; } // The class we could have had! // I am assuming here that the container should have been of T and not int; otherwise why template? template<class T> class test2 { vector<T> v; public: test2() : v(10,1) {} void Report() { copy(v.begin(), v.end(), ostream_iterator<T>(cout, " ")); cout << endl; } };
  4. JimPrice

    Exposing classes to Lua

    Thanks for the response ShotgunNinja. Looks like I actually overthought the problem. The compilation dependency is at the .cpp level and not .h level, so the issues I was imagining - well, weren't really issues.
  5. Hi, I am working more with Lua, and exposing more of my C++ internals to Lua scripting. As part of this process I have a number of classes that need to be exposed to Lua - I am doing this using Luabind. My question is: How do you structure this exposure within C++? Each class that needs exposure requires a luabind::module call. The simplest way to do this would be to have a function do all this calling as part of the initialization process. However, this seems to me to be a large compile-time bottleneck - this one file needs to pull in the header files from each of the classes that needs to be exposed. This seems undesirable. I thought about using a static registration of the form: // .h file struct MyClass { static bool RegisterWithLua(); }; // .cpp file namespace { const bool registered = MyClass::RegisterWithLua(); } bool MyClass::RegisterWithLua() { // Do the actual registration } This works up to the point of needing inheritance, as one can't specify the order of static initializations. So - am I missing something, as I often do? Is there a simple (or even complex) solution to this problem? Or do I just need to suck it up and accept that I will be using one file to expose all my C++ classes? Thanks, Jim.
  6. The issue with ... Sneftel was writing the facade - call_function takes a ... parameter, so if I was writing a facade for luabind I would have needed some way to pass a variable length of parameters to this function - hence in my example above foo could be renamed call_function and bar the facade callthrough. However, this is all now academic, because I am no longer wrapping the luabind library. Jim.
  7. Thanks Sneftel. Quote: LuaBind is the facade. Don't make a hammer factory factory. Yeah, this is what I was starting to feel like. The problem was I started off writing a facade using lua API calls, and then started to integrate luabind after I had already written a fair bit of functionality (plus it was the first time I had really used type-traits on any great scale, so I was all excited). Then, as you say, it started to look like a hammer factory factory. Quote: I'm not sure what you mean by this. Are you having trouble using things like boost::bind with vararg functions? I was under the impression that this sort of thing wasn't valid code in C++: int foo(...) {do something with ...} int bar(...) {foo(...);} Now you are of course either a) You are going to prove me wrong; or b) I am going to look up boost::bind and find all my childhood dreams about ellipses answered. Thanks, Jim.
  8. Hi, I am currently integrating Lua into one of my projects. This mainly uses Luabind. For those who have experience in implementing scripting: Do you litter your code with open lua calls (so, for example, use luabind in the same way you might use the STL), or use a facade class to provide a "ScriptManager" interface for all Lua calls? There seem to be conflicting issues. For example, calling a function using luabind uses: template <class Ret> Ret call_function(lua_State*, const char*, ...) As far as I am aware there is no easy way to pass ... through to a function call, making implementation of a wrapper function awkward (as it so happens, I had already written my own wrapper for function calls using boost::tuple, which I prefer). Similarly, writing a wrapper for the class definition calls is complex - complexity that is already handleded for you in the luabind libraray. So the trade off appears to be between the complexity / time burden of writing wrappers for existing library functionality; versus the benefits of localization of all the library code, something I have always assumed is seen as a good thing. Any thoughts? Jim.
  9. Hi, I'm currently playing with luabind, but am running into problems. I'm not building it as a library, but am just including all headers from the src directory, so the lead in to my test program looks like this: #include <lua.hpp> #include <lualib.h> #include <lauxlib.h> #include <luabind/luabind.hpp> #include <src/class.cpp> #include <src/class_info.cpp> #include <src/class_registry.cpp> #include <src/class_rep.cpp> #include <src/create_class.cpp> #include <src/error.cpp> #include <src/find_best_match.cpp> #include <src/function.cpp> #include <src/implicit_cast.cpp> #include <src/link_compatibility.cpp> #include <src/object_rep.cpp> #include <src/open.cpp> #include <src/overload_rep.cpp> #include <src/pcall.cpp> #include <src/ref.cpp> #include <src/scope.cpp> #include <src/stack_content_by_name.cpp> #include <src/weak_ref.cpp> #include <src/wrapper_base.cpp> When I compile I get some errors - a redefinition of struct luabind::detail::method_name (which appears in class.cpp and class_ref.cpp), and some syntax errors in ref.cpp, and for the life of me I can't work out why they are appearing. Has anyone tried this recently and had any issues? For the record I am using VS 2003 pro with luabind 0.7 and lua 5.1. I vaguely remember reading somewhere that these versions of luabind and lua might not be compatible - and indeed the introduction to the luabind documentation does explicitly say lua 5.0. Is this still the case? 2nd question: Has anyone ever found any reasonable documentation for lua_pushcfunction / lua_pushcclosure? I was also writing a light-weight wrapper, for education purposes as well as the fact that luabind is a beast, and exposing functions to Lua relies upon this function (as well as the function signature int (*func)(lua_State*), which is a whole 'nother issue). I'd like to write an exposure function, but am struggling without knowing what lua_pushcclosure really does. Been through the luabind source, but it's very heavily templated :( So, in summary: Am I using incompatible versions of luabind and lua? If not, has anyone else had any recent issues with compilation of luabind? Or can anyone see a header I am / am not including that I should be? Has anyone ever found any decent information on lua_pushcclosure? Jim. Edit: Don't you hate it when that happens? After spending all morning googling, after writing this post I google "lua 5.1 luabind 0.7" and find some topics of interest. Bah humbug. Still interested in any details on lua_pushcclosure. More edits: Built luabind as a static library, seems to be working. Ah well. If you made it this far, thanks for reading ;) [Edited by - JimPrice on March 6, 2007 3:58:07 PM]
  10. JimPrice

    Const correctness

    Thanks Agony, I realised the reason a few minutes after sitting down away from the PC. Too much programming today :( Jim.
  11. JimPrice

    Const correctness

    I am confused as to what is happening to my constness. This example compiles without warnings or errors on VS2003 pro. #include <vector> struct Mesh { int x; }; class Model { public: const std::vector<const Mesh>& GetMeshes() const {return theMeshes_;} private: std::vector<const Mesh> theMeshes_; }; int main() { Model theModel; // Access method 1 // Why isn't this mesh const? Mesh myMesh = theModel.GetMeshes()[0]; // Access method 2 // The std::vector is no longer const! std::vector<const Mesh> moreMeshes = theModel.GetMeshes(); // Neither are it's contents! Mesh yetAnotherMesh = moreMeshes[0]; } Why is the accessor function Model::GetMeshes not working as a read-only access to the private contents? I probably should know this :( Jim.
  12. JimPrice

    Reading sentences from std::cin

    Razor: Thanks, interesting. You gave me one of those 'eureka' moments, where I finally realised what a stringstream really is. I went back and read over Josuttis (very terse coverage of stringstreams) and then Stroustrup - and found this very example. Something important learned from this! Zahlman: Once more I've been Zahlmanated ;) In response: 0. Yup, that really gets to the crux of the matter. I assumed a blankline would be a read as an eof. 1. My fault, I didn't describe the problem fully. The problem I was having was ending the reading from std::cin and proceding to the std::cout dump. The code as presented was a simple, self-contained example of the code I am actually working on - I was splitting all the sentences into individual words as that bears some resemblance to what's happening in my other code. In retrospect, as that part wasn't relevant to the problem, maybe I should have left that part out. Then again, if I'd done that I wouldn't have seen the stringstream example! 2. Agreed - stringstream would have been easier (and will be implemented in the code this is derived from) and the example was too complicated for the question I was asking. 3. Assuming I wanted individual words. Which I don't. Just for this badly-written example (yeah, yeah, stop rubbing it in) it looks like I do. I am chastened. 4. That's what I had been intending to do, but it relies upon knowing the ctrl-z / ctrl-d thing. I should have written this as a file reader from the beginning, would have made life so much easier. Plus less typing everytime I run the program =/ 4 (part 2). Yeah, that's kinda a hangover from the original code which is a little different. But your point is taken. So - I got the question I wanted answered, had an inspirational moment about stringstreams and learned a lot about posing small self contained examples - make them smaller and more self contained and containing less non-releavant code. Not bad for one question asked! Thanks all, Jim.
  13. It's always the things you think are going to be simple.... The following code reads a sentence (here defined as an arbitary number of words ended with a \n) from std::cin and then dumps the individual words out to std::cout. #include <iostream> #include <string> #include <vector> class SentenceHandler { public: SentenceHandler(); friend std::ostream& operator<<(std::ostream& stream, const SentenceHandler& sentenceHandler); private: std::vector<std::string> words_; }; SentenceHandler::SentenceHandler() { std::string theString; std::getline(std::cin, theString); std::string::size_type idx = theString.find(" "); words_.push_back(theString.substr(0, idx)); while(idx++ != std::string::npos) { std::string::size_type jdx = theString.find(" ", idx); words_.push_back(theString.substr(idx, jdx-idx)); idx = jdx ; } } std::ostream& operator<<(std::ostream& stream, const SentenceHandler& sentenceHandler) { std::copy(sentenceHandler.words_.begin(), sentenceHandler.words_.end(), std::ostream_iterator<std::string>(std::cout, "\n")); return stream; } int main() { SentenceHandler sentenceHandler; std::cout << sentenceHandler; system("pause"); return 0; } However, I am struggling to read an arbitrary number of sentences from std::cin - I'm not quite sure how to read the end of a std::cin stream. I was sure that I could use something like while(std::cin), or while(!std::cin.eof()): SentenceHandler::SentenceHandler() { while(!std::cin.eof()) { std::string theString; std::getline(std::cin, theString); std::string::size_type idx = theString.find(" "); words_.push_back(theString.substr(0, idx)); while(idx++ != std::string::npos) { std::string::size_type jdx = theString.find(" ", idx); words_.push_back(theString.substr(idx, jdx-idx)); idx = jdx ; } } } but apparently I can't (or at least not in the way I thought was possible). I looked at using istream_iterators as well, but I'm not quite seeing how they are used in this regards. Any suggestions? Jim.
  14. And here is the answer using the standard function adaptors, and with boost::bind. #include <vector> #include <iostream> #include <algorithm> #include <functional> #include <boost/bind.hpp> struct Poop { Poop(int i) : id_(i) {} int id_; }; bool ComparePoopToInt(Poop* myPoop, int poorLonelyInt) { return myPoop->id_ == poorLonelyInt; } int main() { std::vector<Poop*> myPoops; myPoops.push_back(new Poop(1)); myPoops.push_back(new Poop(2)); myPoops.push_back(new Poop(3)); std::vector<Poop*>::iterator it = std::find_if( myPoops.begin(), myPoops.end(), std::bind2nd(std::ptr_fun(ComparePoopToInt), 2) ); if(it != myPoops.end()) std::cout << "Success!\n"; it = std::find_if( myPoops.begin(), myPoops.end(), boost::bind(ComparePoopToInt, _1, 2) ); if(it != myPoops.end()) std::cout << "Success Again!\n"; delete myPoops[2]; delete myPoops[1]; delete myPoops[0]; myPoops.clear(); system("pause"); } Jim.
  15. I was looking at this and thinking about boost::lambda, something I've been looking at recently. An alternative to the functor is this: #include <vector> #include <iostream> #include <algorithm> #include <boost/lambda/lambda.hpp> using namespace boost::lambda; struct Poop { Poop(int i) : id_(i) {} bool operator==(int i) {return id_ == i;} int id_; }; int main() { std::vector<Poop*> myPoops; myPoops.push_back(new Poop(1)); myPoops.push_back(new Poop(2)); myPoops.push_back(new Poop(3)); std::vector<Poop*>::iterator it = std::find_if(myPoops.begin(), myPoops.end(), *_1 == 2); if(it != myPoops.end()) std::cout << "Success!\n"; delete myPoops[2]; delete myPoops[1]; delete myPoops[0]; myPoops.clear(); system("pause"); } Jim. Edit: Of course this only makes sense if defining operator== against an int is a natural operation for your class / struct. Maybe there is a boost::bind option for a general comparison function. Hmm, still figuring that out.
  • 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!