Jump to content
  • Advertisement

hkBattousai

Member
  • Content Count

    242
  • Joined

  • Last visited

Community Reputation

191 Neutral

About hkBattousai

  • Rank
    Member

Personal Information

  • Role
    Programmer
  • Interests
    Programming
  1. After studying the parameter packs topic, I was able to find the correct syntax about how to forward parameters packs. I hope this example code helps other people who come across to the same problem in the future. #include <iostream> #include <string> #include <utility> class ClassWithNoDefaultConstructor1 { public: ClassWithNoDefaultConstructor1() = delete; ClassWithNoDefaultConstructor1(const std::string & Str) : String(Str) { } void Print() { std::cout << "ClassWithNoDefaultConstructor1: " << String << std::endl; } private: std::string String; }; class ClassWithNoDefaultConstructor2 { public: ClassWithNoDefaultConstructor2() = delete; ClassWithNoDefaultConstructor2(const int Int, const float Flt) : Integer(Int), Float(Flt) { } void Print() { std::cout << "ClassWithNoDefaultConstructor2: " << Integer << ", " << Float << std::endl; } private: int Integer; float Float; }; template <class T> class ClassWithATemplateDataMemeber { public: template <class ... Arg> ClassWithATemplateDataMemeber(Arg && ... Arguments) : Variable(std::forward<Arg>(Arguments) ...) { } //private: T Variable; }; int wmain(int argc, wchar_t * argv[]) { ClassWithATemplateDataMemeber<ClassWithNoDefaultConstructor1> MyClass1(std::string("String")); ClassWithATemplateDataMemeber<ClassWithNoDefaultConstructor2> MyClass2(5, 3.14f); MyClass1.Variable.Print(); MyClass2.Variable.Print(); system("puase"); return 0; } Output:
  2. I have a template class which is supposed to keep a data member of the template type. When this template type is a class which has no default constructor, I get the obvious compiler error message about the class to be initialized not having a default constructor. How do I initialize this template data member? Is there a generic syntax for this which will work for all possible cases? Example code: #include <string> class ClassWithNoDefaultConstructor1 { public: ClassWithNoDefaultConstructor1() = delete; ClassWithNoDefaultConstructor1(const std::string & Str) : String(Str) { } private: std::string String; }; class ClassWithNoDefaultConstructor2 { public: ClassWithNoDefaultConstructor2() = delete; ClassWithNoDefaultConstructor2(const int Int, const float Flt) : Integer(Int), Float(Flt) { } private: int Integer; float Float; }; template <class T> class ClassWithATemplateDataMemeber { public: ClassWithATemplateDataMemeber() : Variable() // Error here. How to initialize this "Variable"? { } private: T Variable; }; int wmain(int argc, wchar_t * argv[]) { ClassWithATemplateDataMemeber<ClassWithNoDefaultConstructor1> MyClass1; ClassWithATemplateDataMemeber<ClassWithNoDefaultConstructor2> MyClass2; return 0; }
  3. hkBattousai

    VS2017 not compiling small changes

    Visual Studio does this intentionally in order to reduce compile time. I used to experience this issue in an older version of Visual Studio. I am also using version 2017 but I can't reproduce the same issue in my code. Sadly, I can't remember how I solved it then.
  4. You were right. Adding "typename" solved everything. Actually I knew this rule, but I couldn't guess that it was the cause of the errors at this time. Many thanks.
  5. I'm trying to implement my own tree container. I have written a "TreeContainer.h" template class and I am posting a piece of its content below. I have defined a type named "ContainerType", because I am planning to test different other core STL container types later. I want the container type to be define by a "using" or "typedef" macro. I am getting some compiler error messages which I am having a hard time to understand. Every error message is give in the code as comments. Can you please help me understand what I am doing wrong in my code. IDE: Visual Studio 15.7.3 (Language Standard: C++17. Other than that the default compiler options are used.) #include <memory> #include <vector> template <class T> class TreeContainer { public: using pT = T *; using ContainerType = std::vector<pT>; // ... bool DeleteChild(T * const pChild); ContainerType & GetChildren1(); ContainerType & GetChildren2(); // ... private: ContainerType Children; }; // ... template <class T> bool TreeContainer<T>::DeleteChild(T * const pChild) { for (std::vector<T*>::iterator it=Children.begin(); it!=Children.end(); ++it) // Error C2760 syntax error: unexpected token 'identifier', expected ';' { if (pChild == (*it)[i]) { delete *it; Children.erase(cit); return true; } } return false; } template <class T> TreeContainer<T>::ContainerType & TreeContainer<T>::GetChildren1() // ERROR: Error C2061 syntax error: identifier 'ContainerType' { // ERROR1: Error C2447 '{': missing function header (old-style formal list?), ERROR2: Error C2143 syntax error: missing ';' before '{' return Children; } // THIS WORKS template <class T> std::vector<T*> & TreeContainer<T>::GetChildren2() { return Children; } // ... TreeContainer.h
  6. template <class T> class Foo { public: T val; }; template <class T> Foo<T>& operator*=(Foo<T> & left, T right) // 'left.val' and 'right' are considered { // to be the same type (that is 'T'). left.val *= right; // So, if you give different types return left; // for them, the compiler can't deduce 'T' } // since there are two candidates. template <class T, class U> Foo<T> & operator+=(Foo<T> & left, const U & right) // The solution. {     // Allow 'right' to be something else. left.val += static_cast<T>(right);     // Now, 'T' may be equal to 'U', or not. return left; } Foo<float> bar; constexpr int four = 4; constexpr int five = 5; bar *= four; // Error: The compiler can't decide whether 'T' will be 'float' or 'int'. bar += five; // OK: 'T' is deduced to 'float' and 'U' is deduced to 'int'.
  7.   No, I'm not sure. I read the documentation of std::codecvt, but I didn't understand much. I can't find an online example matching my use case. I am totally stuck.
  8. I have an input file named "Input.txt". I have prepared it in Notepad++, then converted to UTF-16 from "Notepad++ Menu > Encoding > Convert to UCS-2 LE BOM". I want to read the contents of this file line by line, then print these lines to a file named "Output.txt".   Here is my code: #include <vector> #include <fstream> #include <string> #include <locale> #include <codecvt> int wmain(int argc, wchar_t *argv[]) { std::vector<std::wstring> Lines; std::wstring Line; const std::wstring LINE_END = L"\n"; std::wifstream InputFileStream(L"C:\\Users\\Administrator\\Desktop\\Test\\Input.txt", std::wifstream::in); InputFileStream.imbue(std::locale(InputFileStream.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>)); while (std::getline(InputFileStream, Line)) { if (Line.size()) // Delete the '\r' character from the line ending mark if it exists. { if (Line.back() == L'\r') { Line.pop_back(); } } Lines.emplace_back(std::move(Line)); } InputFileStream.close(); std::wofstream OutputFileStream(L"C:\\Users\\Administrator\\Desktop\\Test\\Output.txt", std::ios_base::out | std::ios_base::trunc); OutputFileStream.imbue(std::locale(OutputFileStream.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>)); for (uintmax_t i=0; i<Lines.size(); i++) { OutputFileStream << Lines[i] /*<< LINE_END*/ << std::endl; } OutputFileStream.close(); return 0; } Input.txt   Output.txt   Input.txt   Output.txt   Requirements The input and output data must always be kept in UTF-16 encoding. The same text must appear at the output. The line ending format may change. \r\n line endings in the input file may change to \n in the output file, and vice versa. There must be cyclic consistency between the input and output. If I give n-1th output to the nth code run as input, it must give correct and exactly the same output. As I stated in the previous item, the line endings may change after the first run.   How do I make this code run?  
  9.   Of course! Stupid me. I was confused there. We shouldn't worry about the overwritten front element, because it is our purpose to delete it in the first place. I get it now. Thanks a lot. Sorry for the confusion.
  10.   I think there is a bigger problem than the order of elements being changed. The front element is being destroyed unless I understand this code wrongly. Are we assuming, as in BitMaster's answer, that the object's move constructor will swap the data instead of moving it, or do we reserve this front position as the sanctuary of emigrants whose hometowns will be destroyed?
  11. I was looking for how to erase the front element of an std::vector object, and I found the following code here. template<typename T> void pop_front(std::vector<T>& vec) { assert(!vec.empty()); vec.front() = std::move(vec.back()); vec.pop_back(); } As far as I understand, it moves the object at the back (assuming that the contained object is movable) to the front. The object at the back is now empty, and the object at the front is lost since it is overwritten. Then, it detaches the back element, leaving the front one overwritten with the lost back one.   But appearently, it doesn't happen like I said. The documentations says that the front() and back() objects return references. If they did return pointers or iterators and we swapped them, or we swapped the back and front objects with std::swap(), I could understand it. But in this code, it just looks like we overwrite the front element.   Can you please explain me how it works?
  12.   You were right in all points. The source of my problem was as you said, BeginPaint() was not returning the device context correctly. Now my code works correctly. Thank you.   LRESULT CALLBACK WindowMain::ChildWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { switch (uMsg) { case WM_PAINT: { LRESULT lResult = DefSubclassProc(hWnd, uMsg, wParam, lParam); switch (uIdSubclass) { case ID_BT_START: { static const size_t VERTEX_COUNT = 3; // Number of vertexes. (3 for triangle.) static const int LEFT_X = 18; static const int TOP_Y = 8; static const int WIDTH = 14; static const int HEIGHT = 14; static const std::array<Gdiplus::Point, VERTEX_COUNT> VERTEXES{ Gdiplus::Point{LEFT_X, TOP_Y }, Gdiplus::Point{LEFT_X, TOP_Y + HEIGHT }, Gdiplus::Point{LEFT_X + WIDTH, TOP_Y + HEIGHT / 2 }}; PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); // Doesn't return "hDC" correctly. hDC = GetDC(hWnd); // So, I get the correct "hDC" like this. { Gdiplus::Graphics graphics (hDC); const Gdiplus::Pen pen (Gdiplus::Color(255, 0, 0, 0)); const Gdiplus::SolidBrush brshActive (Gdiplus::Color(255, 20, 255, 40)); const Gdiplus::SolidBrush brshInactive(Gdiplus::Color(255, 10, 40, 20)); if (IsWindowEnabled(hWnd)) { graphics.FillPolygon(&brshActive, &VERTEXES[0], VERTEX_COUNT); } else { graphics.FillPolygon(&brshInactive, &VERTEXES[0], VERTEX_COUNT); } graphics .DrawPolygon(&pen, &VERTEXES[0], VERTEX_COUNT); } EndPaint(hWnd, &ps); break; } case ID_BT_STOP: { static const int LEFT_X = 18; static const int TOP_Y = 8; static const int WIDTH = 14; static const int HEIGHT = 14; static const int RADIUS_X = 4; static const int RADIUS_Y = RADIUS_X; PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd, &ps); // Doesn't return "hDC" correctly. hDC = GetDC(hWnd); // So, I get the correct "hDC" like this. { Gdiplus::Graphics Graphics(hDC);                                                 const    Gdiplus::Pen        Pen         (Gdiplus::Color(255, 0,   0,  0));                                                 const    Gdiplus::SolidBrush    brshActive  (Gdiplus::Color(255, 255, 20, 40));                                                 const    Gdiplus::SolidBrush    brshInactive(Gdiplus::Color(255, 40,  10, 20));                                                 if (IsWindowEnabled(hWnd))                                                 {                                                     DrawAndFillRoundedRectangle(Graphics, Pen, brshActive,   LEFT_X, TOP_Y, WIDTH, HEIGHT, RADIUS_X, RADIUS_Y);                                                 }                                                 else                                                 {                                                     DrawAndFillRoundedRectangle(Graphics, Pen, brshInactive, LEFT_X, TOP_Y, WIDTH, HEIGHT, RADIUS_X, RADIUS_Y);                                                 } } EndPaint(hWnd, &ps); break; } } return lResult; break; } default: return DefSubclassProc(hWnd, uMsg, wParam, lParam); } return 0; } void WindowMain::DrawAndFillRoundedRectangle(         Gdiplus::Graphics & Graphics, const Gdiplus::Pen & Pen, const Gdiplus::SolidBrush & Brush, INT X_LEFT, INT Y_TOP, INT WIDTH, INT HEIGHT, INT X_RADIUS, INT Y_RADIUS) { const INT ArcWidth = 2 * X_RADIUS; const INT ArcHeigth = 2 * Y_RADIUS; const float SweepAngle = -90.0f; // Stupid GDI+ sweeps in the negative direction. // The minus sign is to compensate it. Gdiplus::GraphicsPath Path; // Top-Left Arc Path.AddArc( X_LEFT, Y_TOP, ArcWidth, ArcHeigth, -90.0f, SweepAngle); // Left Edge Path.AddLine( X_LEFT, Y_TOP + Y_RADIUS, X_LEFT, Y_TOP + HEIGHT - Y_RADIUS); // Bottom-Left Arc Path.AddArc( X_LEFT, Y_TOP + HEIGHT - ArcHeigth, ArcWidth, ArcHeigth, -180.0f, SweepAngle); // Bottom Edge Path.AddLine( X_LEFT + X_RADIUS, Y_TOP + HEIGHT, X_LEFT + WIDTH - X_RADIUS, Y_TOP + HEIGHT); // Bottom-Right Arc Path.AddArc( X_LEFT + WIDTH - ArcWidth, Y_TOP + HEIGHT - ArcHeigth, ArcWidth, ArcHeigth, -270.0f, SweepAngle); // Right Edge Path.AddLine( X_LEFT + WIDTH, Y_TOP + HEIGHT - Y_RADIUS, X_LEFT + WIDTH, Y_TOP + Y_RADIUS); // Top-Right Arc Path.AddArc( X_LEFT + WIDTH - ArcWidth, Y_TOP, ArcWidth, ArcHeigth, 0.0f, SweepAngle); // Top Edge Path.AddLine( X_LEFT + WIDTH - X_RADIUS, Y_TOP, X_LEFT + X_RADIUS, Y_TOP); Graphics.FillPath(&Brush, &Path); Graphics.DrawPath(&Pen, &Path); }
  13. I have two buttons; namely "Start" and "Stop". My aim is to add icons on them. I subclassed them, then painted with GDI functions. It worked perfectly as expected. Then I tried to do the same thing using GDI+ functions only on the "Start" button. I was going to switch to GDI+ functions on the "Stop" button as well, if I could had succeeded on the "Start" button, but I couldn't. Now, my two buttons look like in the screen shot below.     "Stop" button's icon is painted successfully, but "Start" button's icon is not.   My child window message processor function is as seen below. Note that, the GDI+ code is not currently printing the icon; it desperately tries to draw a simple line.   What am I doing wrong here? Why don't my GDI+ functions work? LRESULT CALLBACK WindowMain::ChildWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { //static const HBRUSH hPlayActive = CreateSolidBrush(RGB(20, 255, 40)); //static const HBRUSH hPlayInactive = CreateSolidBrush(RGB(10, 40, 20)); static const HBRUSH hStopActive = CreateSolidBrush(RGB(255, 20, 40)); static const HBRUSH hStopInactive = CreateSolidBrush(RGB(40, 10, 20)); switch (uMsg) { case WM_PAINT: { LRESULT lResult = DefSubclassProc(hWnd, uMsg, wParam, lParam); switch (uIdSubclass) { case ID_BT_START: { // The code below doesn't work. Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); PAINTSTRUCT                     ps; Gdiplus::Status                Error; HDC hdc = BeginPaint(hWnd, &ps); { Gdiplus::Graphics graphics(hdc); Gdiplus::Pen pen(Gdiplus::Color(255, 0, 0, 255)); Error = graphics.DrawLine(&pen, 0, 0, 20, 10);    // Always returns "0 (Ok)". } EndPaint(hWnd, &ps); Gdiplus::GdiplusShutdown(gdiplusToken); EndPaint(hWnd, &ps); // It works if I use the commented out code block below. /*static const size_t VERTEX_COUNT = 3; // Number of vertexes. (3 for triangle.) static const int LEFT_X = 18; static const int TOP_Y = 8; static const int WIDTH = 14; static const int HEIGHT = 14; static const std::array<int, VERTEX_COUNT> VERTEXES{    LEFT_X, TOP_Y }, LEFT_X, TOP_Y + HEIGHT },                 LEFT_X + WIDTH, TOP_Y + HEIGHT / 2 }}; HDC hDC = GetDC(hWnd); if (IsWindowEnabled(hWnd)) { SelectObject(hDC, hPlayActive); } else { SelectObject(hDC, hPlayInactive); } PolyPolygon(hDC, &(VERTEXES[0]), &VERTEX_COUNT, 1); ReleaseDC(hWnd, hDC);*/ break; } case ID_BT_STOP: { // The following legacy GDI version works as expected. static const int LEFT_X = 18; static const int TOP_Y = 8; static const int WIDTH = 14; static const int HEIGHT = 14; static const int RADIUS_X = 2; static const int RADIUS_Y = 2; HDC hDC = GetDC(hWnd); if (IsWindowEnabled(hWnd)) { SelectObject(hDC, hStopActive); } else { SelectObject(hDC, hStopInactive); } RoundRect(hDC, LEFT_X, TOP_Y, LEFT_X + WIDTH, TOP_Y + HEIGHT, RADIUS_X, RADIUS_Y); ReleaseDC(hWnd, hDC); break; } default: return DefSubclassProc(hWnd, uMsg, wParam, lParam); } return lResult; break; } case WM_DESTROY: switch (uIdSubclass) { case ID_BT_START: { //DeleteObject(hPlayActive); //DeleteObject(hPlayInactive); break; } case ID_BT_STOP: { DeleteObject(hStopActive); DeleteObject(hStopInactive); break; } } return DefSubclassProc(hWnd, uMsg, wParam, lParam); break; default: return DefSubclassProc(hWnd, uMsg, wParam, lParam); } return 0; }
  14.   But why? Can you please explain it? It is said that, the vector elements are contiguous in the memory. When I add a new list element, the vector must reallocate in order to preserve its contiguous structure. How do you disprove this?
  15. I have divided my 2D game map into 100x100 pixel pieces (the map size will be integer multiple of dimensions of the piece size). Each map piece contains a list of map objects in it; so that a short list of nearby game object will be available all the time for each given location on the map. I preferred this structure in order to increase performance of the collision detection algorithm.   My question is: What will happen to the memory allocated by std::vector<MapPieces> when I add a new game object pointer to any of the GameObjects instance? I mean, when a game object overlaps the area of a MapPiece instance and I add its pointer the the GameObjets list, will the entire std::vector<MapPieces> reallocate in the memory? If yes, what kind of container should I prefer instead of std::list<std::shared_ptr<GameObject>> GameObjects? class GameMap { public: // ... std::vector<MapPiece> MapPieces; // ... }; class MapPiece { public: // ... std::list<std::shared_ptr<GameObject>> GameObjects; // ... };
  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!