• Advertisement


  • Content count

  • Joined

  • Last visited

Community Reputation

462 Neutral

About Ftn

  • Rank
  1. Usually my main.cpp file is just a few lines. Then there's program.cpp or application.cpp. After that it gets more domain specific, high level class what the application does. Then there might be 10 more layers all down to the lowest level classes and functions. It all depends how big the program is. You should introduce higher level abstractions whenever the program grows too big, or if you know the requirements beforehand you can try to do it prematurely (beware of overengineering).   I'm sure if you can give an example, many of us can give our thoughts.
  2. Book might be useful when dealing with Win32, but surely not when dealing with C++. Win32 is a C API. 10 years ago it was all clumped together as C/C++. C++ is totally different language than C.   Anyway, that was just a side-comment in my post.
  3. virtual destructor

    Wrong conclusion. Those base classes don't need virtual destructors because they aren't freed by calling delete on a pointer to the base class, not because they have no resources in the base class.   Yes. But if you're making exception safe engine, you have to call the Destroy() functions automatically.. And for that you have to wrap it with virtual destructor. Sorry I wasn't specific enough in the exaple.   EDIT: Only because documentation says they're COM objects.I remember that some of those wasn't really a COM object. Might remember be wrong. Haven't seen that deprecated crap in years.
  4. unique_ptr

    You're right. I wasn't specific enough and was thinking only about lvalues as seen in first example here.   EDIT: Ok I'll try to be a bit constructive.   Example1: You're right, destructors for std::vector and std::unique_ptr p are called when leaving from scope. (std::unique_ptr needs a type btw). You are moving first element of the vector to the variable p. Your Foo type is still destructible after being moved-from. You should see 11 messages. This means you're constucting 10 Foo objects and destructing 11 of them.   Example2: BaseResourceObject is not used at all. I don't think Manager should have Run() virtual function. Manager is not a concrete class, I can't see the Insert() implementation. GetResource() method accesses unknown member.   I've used similar classes alot. I've named the classes something like asset_cache, what you call Manager. It doesn't need to be virtual. It's ok to store resource as unique_ptr and return just a reference, just make sure the Manager is destructed after all other objects who have access to the reference.
  5. virtual destructor

    You don't actually need virtual destructor if base class doesn't have any resources (or destructor defined). Omitting virtual destructor from virtual class really confuses developers though.   D3DX11 asynchronous loading/processing base classes have virtual functions without virtual destructors, which are meant to be inherited. You need derive them and introduce virtual destructor to make them work correctly.
  6. unique_ptr

      Operator = on unique pointer is forbidden, and std::move won't delete it. Also you'r exaple has unique_ptr parameter as value, which shouldn't compile (not copy-constructible)       I'm pretty sure you should use shared_ptr for resource construction. FleBlanc describes good when manager shouldn't keep resources alive, with weak_ptr.   Resource from unique_ptr is not meant to be shared. Unless if the lifetime stucture is very clear, and the destruction and access patterns are well defined.
  7. Not sure what language this is, but if it's C++, then I've experienced it's good to wrap everything what the Win32 API is to proper exception handling. It's a bit tedious work at first, but pays off whenever you have more than two callsites for some win32 function.   If this is C++, then first natural step is to place one class per source/header, unless there's some good reason not to. Most likely this is an issue of layering classes from high-level to low-level.   I'm interested about what Petzold's book you're reading (I hope its not +10 year old book). I'm not fan of his earlier works, and now looking the bibliography it doesn't seem promising.
  8. <p>*edit: deleted bunch of code, becouse its most likely wrong and forum formatting is so ugly.</p>
  9. I'm not sure if I should create new topic about this, I don't like creating topics around here.. I experimented with std allocators somewhat.   I did some benchmarks some years ago. It's easy to beat standard allocator (like 400% faster and in 25% memory overhead vs node allocation) if you can restrict to single threaded, and pool in user space.std::new is fast, and its very difficult to create benchmark to measure real usage. delete and repeated realloc is harder to beat. I did bunch of hand crafted free lists for x86 and x64 builds.   The effort, and risk for bugs is so great that IMO for consumer product it's not worth it.   Here's partial spam of the code. The idea I had was to separate allocation and construction, and have one or few shared pooled and paged allocators in user memory space, for std::vector, std::list and others. A lot of hand crafted containers omitted. You could craft multithreaded per thread allocator which would be faster, but I didn't have time to figure the synch for multithreaded deallocation. The point was to separate the allocation and construction of objects.   [source] #define _HAS_ITERATOR_DEBUGGING 0 #define _SCL_SECURE 0 #include "block_memory.h" #include "pt/std/map.h" #include <iostream> using namespace boost; namespace pt { template<typename T> struct construction {     construction() {}     construction(int) {}     __forceinline void construct(T* __restrict ptr, T const& t)     {         void* __restrict vptr = ptr;         ::new (vptr) T(t);     }     __forceinline void destroy(T* __restrict ptr)     {         ptr->~T();         ptr;     } }; template<typename T> struct memory {     typedef T value_type;     typedef value_type* pointer;     typedef value_type& reference;     typedef value_type const* const_pointer;     typedef value_type const& const_reference;     typedef std::size_t size_type;     typedef std::ptrdiff_t difference_type;     inline size_type max_size() const     {         // estimate maximum array size         size_type count = (size_type)(-1) / sizeof(T);         return (0 < count ? count : 1);     }     inline pointer allocate(size_type count)     {         // allocate storage for count elements of type T         return (T*)::operator new(count * sizeof(T));     }     inline void deallocate(pointer ptr, size_type)     {         ::operator delete(ptr);     }     inline pointer address(reference r) const     {         return &r;     }     inline const_pointer address(const_reference r) const     {         return &r;     } }; #include "paged_block_data.h" #include "pt/boost/shared_ptr.h" namespace pt { #define PT_INLINE __forceinline // Tells the compiler that the function returns an object that will not be // aliased with any other pointers. Will propagate. #define PT_RESTRICT_FUNC __declspec(restrict) class block_memory { public: // type definitions     typedef int value_type;     typedef value_type* pointer;     typedef value_type& reference;     typedef value_type const* const_pointer;     typedef value_type const& const_reference;     typedef std::size_t size_type;     typedef std::ptrdiff_t difference_type;     static size_t const data_size = sizeof(value_type); public:     block_memory(shared_ptr<paged_block_data> const& data);     shared_ptr<paged_block_data> const& data() const;     // std::allocator interface     size_type max_size() const;     pointer address(reference r) const;     const_pointer address(const_reference r) const;     template<size_t ElementSize>     PT_INLINE PT_RESTRICT_FUNC pointer allocate_element();     template<>     PT_INLINE PT_RESTRICT_FUNC pointer allocate_element<12>()     {         return reinterpret_cast<pointer>(m_block_data->allocate_16());     }     template<>     PT_INLINE PT_RESTRICT_FUNC pointer allocate_element<16>()     {         return reinterpret_cast<pointer>(m_block_data->allocate_16());     }     template<>     PT_INLINE PT_RESTRICT_FUNC pointer allocate_element<24>()     {         return reinterpret_cast<pointer>(m_block_data->allocate_32());     }     template<size_t ElementSize>     PT_INLINE void deallocate_element(value_type* __restrict ptr);     template<>     PT_INLINE void deallocate_element<12>(value_type* __restrict ptr)     {         m_block_data->deallocate_16(ptr);     }     template<>     PT_INLINE void deallocate_element<16>(value_type* __restrict ptr)     {         m_block_data->deallocate_16(ptr);     }     template<>     PT_INLINE void deallocate_element<24>(value_type* __restrict ptr)     {         m_block_data->deallocate_32(ptr);     } private: // data members     shared_ptr<paged_block_data> m_block_data; }; inline block_memory::block_memory(shared_ptr<paged_block_data> const& data) : m_block_data(data) { } inline shared_ptr<paged_block_data> const& block_memory::data() const {     return m_block_data; } inline block_memory::size_type block_memory::max_size() const {     // estimate maximum array size     size_type count = (size_type)(-1) / data_size;     return (0 < count ? count : 1); } PT_INLINE  block_memory::pointer block_memory::address(reference r) const {     return &r; } PT_INLINE  block_memory::const_pointer block_memory::address(     const_reference r) const {     return &r; } template<typename T> struct typed_block_memory : public block_memory {     typedef T value_type;     typedef value_type* __restrict pointer;     typedef value_type& reference;     typedef value_type const* __restrict const_pointer;     typedef value_type const& const_reference;     typedef std::size_t size_type;     typedef std::ptrdiff_t difference_type;     explicit typed_block_memory(shared_ptr<paged_block_data> const& data)     : block_memory(data)     {     }     inline size_type max_size() const     {         // estimate maximum array size         size_type count = (size_type)(-1) / sizeof(value_type);         return (0 < count ? count : 1);     }     inline pointer allocate(size_type count)     {         assert(count == 1); count;         block_memory::pointer ptr             = block_memory::allocate_element<sizeof(T)>();         return reinterpret_cast<pointer>(ptr);     }     inline void deallocate(pointer ptr, size_type count)     {         block_memory::pointer block_ptr             = reinterpret_cast<block_memory::pointer >(ptr);         count;         block_memory::deallocate_element<sizeof(T)>(block_ptr);     }     inline pointer address(reference r) const     {         return &r;     }     inline const_pointer address(const_reference r) const     {         return &r;     } }; template<typename T> class node_allocator : public construction<T>, public typed_block_memory<T> { public:     typedef T* pointer;     // convert an allocator<T> to an allocator<Other>     template<class Other>     struct rebind     {         typedef node_allocator<Other> other;     };     template<typename U>     node_allocator(node_allocator<U> other)     : typed_block_memory(other.data())     {     }     template<typename C, typename M>     node_allocator(C const& c, M const& m)     : construction(c)     , typed_block_memory(m)     {     } }; class untyped_node_allocator { public:     typedef void* pointer;     // convert an untyped_node_allocator to an allocator<Other>     template<class Other>     struct rebind     {         typedef node_allocator<Other> other;     };     template<typename U>     untyped_node_allocator(node_allocator<U> other)     : m_memory_parameter(other.data())     {     }     template<typename C, typename M>     untyped_node_allocator(C const&, M const& m)     : m_memory_parameter(m)     {     }     template<class Other>     operator node_allocator<Other>()     {         return node_allocator<Other>(0, m_memory_parameter);     }     shared_ptr<pt::paged_block_data> m_memory_parameter; }; void test_main() {     shared_ptr<paged_block_data> block_data(new paged_block_data);     block_data->reserve();     untyped_node_allocator untyped_alloc(0, block_data);     std::list<int,untyped_node_allocator> int_test(allocator); } // namespace pt   [/source]
  10. Sorry I'm in a hurry at the moment, but I think STD allocators should be copyable. You don't have copy constuctor.   I think the answer is to have mMemory wrapped in std::shared_ptr.
  11. Sorry to skim much of the answers here, so this might be redundant.   All threads can be running the same assembly code instructions simultaneously without a problem.   The code they're running will access some memory. This memory must be synchronized. Each thread has own registers for the code, but if the code shares the same memory, you must deal with it.
  12. The OP is specifically talking about singletons. The title is just misleading. The suggestion to use singletons is void. The singleton has many ways lagging a project weeks behind. I remember one time when we had a templated singleton, that is static data member in header file. The result was that we had 2 different singletons in different translation units. This was the at the same time we we're battling about the construction and destruction order. Funny thing about destruction is, that if singleton object being destructed (after main() returns) refers to another singleton, and that singleton have already been destructed, the access function (class.instance() or such) recreates it. It's destructor is not gonna be called again.   My suggestion is to wrap the global parameter you want to RAII object, and while it's alive, global access is possible. Any access outside of the scope guarded object should throw exception or cause abort(). This way you can manage the lifetimes of everything, and any access to non-living objects are caught at development time.   I can give example of my suggestion if you need one (or other members here).
  13. Best language to start programming in?

    C++'s strength is the RAII, and it's weakness's are the C compatibility and weak library support. You need ton of knowledge to set up environment and write basic Win32 application without using some crappy GUI library (and all GUI libraries in c++ are crappy imo). Most of the internet, books and open source projects practice poor c++ programming practices. You need to be very careful not to inject your program with a crappy API. And when you decide what xml, networking, sound, and math libraries you'll use, they will be all in different coding style. Unless you wrap them (all and whole API's) all up, you're left with source code with 5 different coding conventions and workaround for the poor quirks from their poor design. C# has extensive library, and it's all uniform syntax. Even 3rd party libraries follow the MS conventions. It also has better IDE and dev tools. It is much faster to develop at the beginning. There are many design flaws in the dotnet classes, some originating from the flaws of the language, and some just poor OO design. In the end it can get very verbose syntax wise (even more so than c++), and you have to be very careful if you want to do anything deterministically. Java's design has been flawed from get-go, and the repairs haven't worked yet. Overall, at high level, most concise source code will come from c++, but getting there will take lot of of code and might require you to build "meta language" with lower level classes first. Now, after being out of picture for a long time for c++, Microsoft seems to invest heavily in (modern) c++ now. Maybe they will try to create some decent library for the first time ever. There's even some hints that they might try and make native compiler for C#.
  14. Win32 API is not good c++. All sample code usually omit most of the error checking to keep it short. Samples are almost never good enough to be used as is. (If function returns an error code, then it should be checked, etc.) For c++ network programming, maybe try setting up and playing with boost::asio [url="http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/overview/networking/protocols.html"]http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/overview/networking/protocols.html[/url] For general advanced c++ programming: [url="http://www.drdobbs.com/cpp"]http://www.drdobbs.com/cpp[/url] [url="http://cpp-next.com/"]http://cpp-next.com/[/url] (mostly about advanced c++11 stuff and future of c++) [url="http://www.parashift.com/c%2B%2B-faq-lite/"]http://www.parashift.com/c%2B%2B-faq-lite/[/url] [url="http://herbsutter.com/"]http://herbsutter.com/[/url] [url="http://scottmeyers.blogspot.com/"]http://scottmeyers.blogspot.com/[/url] [url="http://isocpp.org/blog/category/articles-books"]http://isocpp.org/blog/category/articles-books[/url] And everything the authors of those blogs have written in past 10 years. Microsoft seems to finally try invest in some decent c++ code: Welcome Back to C++ (Modern C++) [url="http://msdn.microsoft.com/en-us/library/hh279654.aspx"]http://msdn.microsoft.com/en-us/library/hh279654.aspx[/url] Rather old, but still better than most guidelines. Really paved the modern c++ in for me 10 years ago. (important stuff starts from section 5 onwards, but there are some outdated advices. Also harder to google, year after year) [url="http://files.rsdn.ru/19450/coding_guidelines.html"]http://files.rsdn.ru/19450/coding_guidelines.html[/url]
  15. First, that is pretty well done, very easy to read. I noticed this: [quote name='Khatharr' timestamp='1353036021' post='5001432'] I see main()'s board getting passed into a lot of member functions. Why not make it a member variable? [/quote] Which brings me to the issue that this whole program has only static methods. So the suggestion of adding a member variable wont work. How about trying to create a class called Board and instantiate it? It wont make the source code shorter, but it will focus some code to specific place. It will increase the so called cohesion ([url="http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29"]http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29[/url]) for different elements (or compononents/modules/concepts) of your program. Basically most of you operations of the board data would be abstracted away there. The Board class could have methods such as: Clear() Draw() IsElementFree() (SpaceFree) MakeMove() IsFull() Also, you can add loops inside of your CheckWinner() method.
  • Advertisement