Friday, October 6, 2017

It's magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'.

'std::bind' makes a instance of 'std::function' within user-defined parameter.

You don't need to consider how does 'std::bind' work, just learn how to use it.

Anyway, let's have a look at examples.

#include <iostream>
#include <functional>

std::function<void()> func;

void no_arg()
{
  std::cout << "no_arg\n";
}

void int_arg(int i)
{
  std::cout << "int_arg " << i << std::endl;
}

class Foo
{
  public:
  void no_arg_method() {
    std::cout << "no_arg_method\n";
  }
};

int main()
{
  // func and no_arg are both take no arguments, so we can assign no_arg to func directry
  func = &no_arg;
  func();
  
  // int_arg takes one int argument, so we need to use std::bind to make new function object
  // with int_arg taking one argument of 10.
  func = std::bind(&int_arg, 10);
  func(); // no arguments provided here.
  
  // Foo::no__arg_method takes no arguments, but it needs implicit argument of 'this',
  // std::bind can bind instance address like this.
  Foo foo;
  func = std::bind(&Foo::no_arg_method, &foo);
  func(); // calls foo's no_arg_method

}
repl.it

And here is one more example, with function object taking arguments.

#include <iostream>
#include <functional>

std::function<void(int i)> func;

void int_arg(int i)
{
  std::cout << "int_arg " << i << std::endl;
}

void int_arg2(int i, int j)
{
  std::cout << "int_arg2 " << i << "/" << j << std::endl;
}

class Foo
{
  public:
  void int_arg_method(int i) {
    std::cout << "int_arg_method " << i << std::endl;
  }
};

int main()
{
  // func and no_arg are both take one int argument, so we can assign int_arg to func directry
  func = &int_arg;
  func(20); // call with argument;
  
  // int_arg2 takes two int argument, so we need to use std::bind to make new function object
  // with int_arg2 taking one argument(10 for instance).
  // std::placeholders::_1 means that 'will be replaced by first argument by caller' 
  func = std::bind(&int_arg2, 10, std::placeholders::_1);
  func(20); // std::placeholders::_1 is replaced to 20
  
  // also we can use placeholders with class method.
  Foo foo;
  func = std::bind(&Foo::int_arg_method, &foo, std::placeholders::_1);
  func(20);

}
repl.it


Tuesday, September 5, 2017

Game loop and multi-threading in game programming

In most of games, the game status will change in every moment, even if there is no user input.

So game program must have game loop, which updates internal status time by time.

The game loop looks like this.

#include <chrono>
#include <thread>

using namespace std::chrono;

void game_loop()
{
    while(true)
    {
        steady_clock::time_point begin = steady_clock::now();

        input();            // receive and store user input.
        update();           // update game.
        draw_screen();      // draw.

        steady_clock::time_point end = steady_clock::now();

        constexpr fps = milliseconds(1000/60); // 60 frames per second
        milliseconds elapsed_time = duration_cast<milliseconds>(end - begin);

        if( fps > elapsed_time ) {
            std::this_thread::sleep_for( fps - elapsed_time ); // wait for next frame
        }
    }
}

Each loop is called 'frame'. In this example each frame is intended to be called 60 times per second.
If one frame takes more than 1/60 second, the game will get slower.

So, we have to take care not to take 1/60 second in one frame.

In game program, tipical long-time task is loading resource(3D models, texture, database, etc.).
If the program execute loading resource in 'update()', the game will stop at the frame.

Multi-threading is used to solve this kind of problem.
In 'update()', when the program desides to load some resource, create loading request to other thread.
The thread loads the resource, and send the data back to main thread.

The game loop will be going, even when loading resource.


Wednesday, August 30, 2017

May the CONST be with you

In C++, 'const' is a important keyword to avoid bugs.

Declaring item of some kind of game, it will be like this.

class Item
{
    int _count;
    std::string _name;

public:
    Item(std::string const& name, int count)
    :_name(name), _count(count) {}
    
    std::string const& Name() {
        return _name;
    }
    int Count() {
        return _count;
    }
};

And let's implement a function for print Item.

// take reference to avoid copying object, and set const to avoid modifying that.
void PrintItem(Item const& item)
{
    std::cout << "name: " << item.Name() << " count:" << item.Count();
}
This is good idea to set 'const' for read-only reference. It prevents to modify data unintendedly. But the code above gets compile-time error.
error: passing 'const Item' as 'this' argument of 'const string& Item::Name()' discards qualifiers [-fpermissive]
error: passing 'const Item' as 'this' argument of 'int Item::Count()' discards qualifiers [-fpermissive]
Compiler says calling Item::Name() and Item::Count() may modify the internal data of Item. We humans know the Item::Name() and Item::Count() never modify data, but compiler doesn't. So we need to tell the compiler that Item::Name() and Item::Count() does not modify data like this.
class Item
{
    int _count;
    std::string _name;

public:
    Item(std::string const& name, int count)
    :_name(name), _count(count) {}
    
    std::string const& Name() const {   // 'const' after function name tells the function never modify internal data.
        return _name;
    }
    int Count() const {   // The same to above.
        return _count;
    }
};

Now we can compile and call the PrintItem() function.

What if a function declared as 'const' modifies internal data?
It gets compile-time error too.




What is copy constructor?

Copy constructor is used to copy instance.
We need to declare copy constructer when simple memory copying is undesirable.

For example, let's make variable length string class.

#include <iostream>
#include <string.h>

using namespace std;

class MyString
{
    char* str;
public:
    MyString() { str=nullptr; }
    ~MyString() { delete str; }

    void set(char const* src) {
        // delete existing memory and allocate enough new memory.
        delete str;
        str = new char[strlen(src)+1];    // danger code... don't care here.
        strcpy(str, src);
    }
    char* const get() {
        return str;
    }
};

void test(MyString copy_of_s)
{
    copy_of_s.set("abc"); // step 3
}

int main()
{
    MyString s;
    s.set("hello");    // step 1
    cout << s.get() << endl;   // output: hello
    test(s);           // step 2
    cout << s.get() << endl;   // step 4 -- what will be printed?
}

This class has no copy constructer yet.
What will happne on step 4??
Our program intend to print "hello". because test() takes a copy of MyString, so 's' will not be changed by the function.
But actually this program accesses dangling pointer on step 4.

Here describe the memory status step by step.

step 1 --- create MyString instance and set "hello".


step 2 --- copy instance by calling function


step 3 --- set "abc" to copied instance.


At this point, the memory storing string "hello" is deleted by MyString::set() funciton.
So at the step 4 MyString::get() function accesses the deleted memory.

To solve the problem, we should declare copy constructor.

class MyString
{
    char* str;
public:
    MyString() { str=nullptr; }
    ~MyString() { delete str; }

    // copy constructor.
    // take reference to source instance, allocate new memory and copy string holded by src.
    MyString(MyString const & src) {
        this->str = new char[strlen(src.str)+1];
        strcpy(this->str, src.str);
    }

    void set(char const* src) {
        // delete existing memory and allocate enough new memory.
        delete str;
        str = new char[strlen(src)+1];    // danger code... don't care here.
        strcpy(str, src);
    }
    char* const get() {
        return str;
    }
};

When calling test(), MyString(MyString const &src) is called.
Memory is managed properly, and say hello twice!



Wednesday, August 23, 2017

Enum with string

If you need enums and strings that are equivalent as that names, You can declare like this.

#define ENM \
E(AAA)\
E(BBB)

#define E(x) x,
enum {
    ENM
};
#undef E

#define E(x) #x,
const char* strs[] = {
    ENM
};
#undef E

int main() {
    cout << AAA << endl;          // 0
    cout << strs[AAA] << endl;    // AAA
    return 0;
}

Tuesday, August 22, 2017

Reducing #includes in header

In C++, '#include' is an easy way to import other module.

But we need to consider the side-effect of #include. It may be big deal some time.

for example,
file: module_a.hpp
------------------------------------------
class ModuleA
{
    ...
    ...
};
file: module_a.cpp
------------------------------------------
#include "module_a.hpp"
...
...
file: module_b.hpp
------------------------------------------

#include "module_a.hpp"

class ModuleB
{
    ModuleA module_a;
    ...
    ...
};
file: module_b.cpp
------------------------------------------
#include "module_b.hpp"
...
...

file: main.cpp
------------------------------------------

#include "module_b.hpp"

int argc, char *argv[])
{
    ModuleB module_b;

    ...
    ...
}

...What's wrong??
C++ programmer always do like this.

Then let me show another approach.

file: module_a.hpp
------------------------------------------
class ModuleA
{
    ...
    ...
};
file: module_a.cpp
------------------------------------------
#include "module_a.hpp"
...
...

file: module_b.hpp
------------------------------------------
#include <memory>
class ModuleA;

class ModuleB
{
    std::unique_ptr<ModuleA> module_a;
    ...
    ...
};
file: module_b.cpp
------------------------------------------
#include "module_b.hpp"
#include "module_a.hpp"

...
...

file: main.cpp
------------------------------------------
#include "module_b.hpp"

int argc, char *argv[])
{
    ModuleB module_b;

    ...
    ...
}

The point is the position of '#include "module_a.hpp"'.
Include-dependencies are different.

In the first pattern, the dependency is,
main.cpp --> module_b.hpp --> module_a.hpp
module_b.cpp --> module_b.hpp --> module_a.hpp
module_a.cpp --> module_a.hpp

The second pattern,
main.cpp --> module_b.hpp
module_a.cpp --> module_a.hpp
module_b.cpp --> module_b.hpp
             --> module_a.hpp

If module_a.hpp is modified, the first pattern needs all files to be re-compiiled.
The second pattern needs module_a.cpp, module_b.cpp to be re-compiled.

It looks a small matter in this example, but in big project, it will make a significant difference of buiding time.

Generally, it's not recommended including file in header.
except these cases.
- Headers of library. It will not be modified in future.
- Templates. We need to include template to instanciate the actual declaration.
- Parent class to inherit.







What is function object ?

std::function is a class for 'function object'.
This is powerful way to represent predicator.

Let's see how to use it.

First, I show a sample with no 'std::function's.

// Predicator class(i.e., has operator() ) which take int for argument and returns int by adding it's internal value.
class Adder
{
public:
    int to_add;
    int operator()(int a) {
        return a + to_add;
    }
};

// Another predicator doing multiply.
class Multiplier
{
public:
    int to_mul;
    int operator()(int a) {
        return a * to_mul;
    }
};

// Some class having std::vector<int>
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    template <typename T>
    void apply(T pred) {
        for(int& elm : vec) {
            elm = pred(elm);         //the predicator is intended to have 'int operator(int)'
        }
    }
};

// some function
void Bar(Foo& foo, int to_add, int to_mul)
{
    Adder adder;
    adder.to_add = to_add;
    foo.apply(adder);   // add for each int

    Multilier multi;
    multi.to_mul = to_mul;
    foo.apply(multi);   // mulply for each int
}

We need to declare predicator class for each calcuration( adding and multipling )
Next, let's do this using std::function.

// Some class having std::vector<int>
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    void apply(std::function<int(int)> func) {  //take std::function which take int as argument, and returns int.
        for(int& elm : vec) {
            elm = func(elm);      // call the func
        }
    }
};

int add(int a, int to_add) { return a+to_add; }
int mul(int a, int to_mul) { return a*to_mul; }

void Bar(Foo& foo, int to_add, int to_mul)
{
    //std::bind() makes std::function instance holding function pointer with internal values.
    //std::placeholders::_1 means the argument will passed by caller.

    std::function<int(int)> adder = std::bind(&add, std::placeholders::_1, to_add);
    //so, 'adder' has a pointer to function 'add' and a value 'to_add'.
    //first argument will be passed by the caller.

    foo.apply(adder);   // add 2 for each int

    //std::function to multiply.
    std::function<int(int)> multi = std::bind(&mul, std::placeholders::_1, to_mul);

    foo.apply(multi);   // mulply 3 for each int
}

std::function can have any value in it. and has operator() of specified type signature.
for example,
std::function<int(float)>  -  function object that take float for arugment, returns int.
std::function<std::string(double, int)>   - function object that take double and int, returnts std::string

Next, let's make this example shorter with lambda expression.

// Some class having std::vector
class Foo
{
    std::vector<int> vec;
public:

    // apply predicator.
    void apply(std::function<int(int)> func) {  //take std::function which take int as argument, and returns int.
        for(int& elm : vec) {
            elm = func(elm);      // call the func
        }
    }
};

void Bar(Foo& foo, int to_add, int to_mul)
{
    // lambda expression can make function object in line.
    std::function<int(int)> adder = [to_add](int a) -> int { return a+to_add; };

    foo.apply(adder);   // add 2 for each int

    std::function<int(int)> multi = [to_mul](int a) -> int { return a*to_mul; };

    foo.apply(multi);   // mulply 3 for each int
}

With std::function, we can easily declare predicator and make the program more flexible.







It&#39;s magic! std::bind

'std::bind' is a powerful helper for working around 'std::function'. 'std::bind' makes a instance of 'std::fun...