Cocos2d-x には CREATE_FUNC というマクロがあります。これは以下の実装になっています。

#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
    __TYPE__ *pRet = new __TYPE__(); \
    if (pRet && pRet->init()) \
    { \
        pRet->autorelease(); \
        return pRet; \
    } \
    else \
    { \
        delete pRet; \
        pRet = NULL; \
        return NULL; \
    } \
}

これを以下の様に使うことで、autorelease 済みの TestLayer オブジェクトを生成できます。

class TestLayer : public cocos2d::Layer {
public:
    bool init();
    CREATE_FUNC(TestLayer);
};

ただ、これには問題があります。 マクロを見れば分かるように、createinit 関数はパラメータを持ちません。 つまり、初期化する際に引数を渡したい場合、CREATE_FUNC を利用できません。

もし値を渡したい場合、CREATE_FUNC マクロがやっていることを手動で書く必要があります。

class TestLayer : public cocos2d::Layer {
public:
    bool init(int n, std::string s);
    static TestLayer* create(int n, std::string s) {
        auto p = new TestLayer();
        if (p->init(n, s)) {
            p->autorelease();
            return p;
        } else {
            delete p;
            return nullptr;
        }
    }
};

これはちょっと書くのが面倒過ぎます。 さらに init 関数のオーバーロードが増えると、create 関数の実装も増え、更に面倒になります。

これを解決するため、以下のクラスを作りました。

#include<utility>

template<class Derived>
struct create_func {
    template<class... Args>
    static Derived* create(Args&&... args) {
        auto p = new Derived();
        if (p->init(std::forward<Args>(args)...)) {
            p->autorelease();
            return p;
        } else {
            delete p;
            return nullptr;
        }
    }
};

Variadic Templates や Perfect Forwarding を使っているので、C++11 限定です。Cocos2d-x 3.0 を使うなら問題にならないでしょう。

これは以下の様に利用します。

class TestLayer : public cocos2d::Layer, create_func<TestLayer> {
public:
    bool init(int n);
    bool init(int n, std::string s);
    using create_func::create;
};
auto p = TestLayer::create(10); // init(10) が呼ばれる
auto p2 = TestLayer::create(10, "aaa"); // init(10, "aaa") が呼ばれる

CRTP を使っているため、create_func<TestLayer> と書く手間が発生します。が、それを書くだけで create 関数に値を渡すことでき、init 関数のオーバーロードもできます。

create 関数を書くのが面倒になったら、このクラスを利用することを考えましょう。