7

私はnトンの基本クラステンプレートに取り組んでいます。私はまだ怠惰について心配していないので、意図は次のとおりです。

クラスにn個のインスタンスしかないことを確認し、それらへのグローバルアクセスポイントを提供します。

これまでの私のコードは次のとおりです。

template<typename Derived, size_t n = 1>
class n_ton_base                 // Singletons are the default
{
    static Derived instances[n + (n == 0)];
                              // Zerotons are supported, too
protected:

    // Prevent n_ton_base to be used outside of inheritance hierarchies
    n_ton_base() {} 

    // Prevent n_ton_base (and Derived classes) from being copied
    n_ton_base(const n_ton_base&) = delete;

public:
                   // Get first element by default, useful for Singletons
    template<size_t i = 0>
    static Derived& get_instance()
    {
        static_assert(i < n, "Time to increase n it seems!");
        return instances[i];
    }
};

そして、これがそれをどのように使うかです:

class SingletonExample : public n_ton_base<SingletonExample>
{
public:
    void method()
    {
        std::cout << "Singletons are overused.\n";
    }    
};

class DoubletonExample : public n_ton_base<DoubletonExample, 2>
{
public:
    void method()
    {
        std::cout << "Doubleton " << this << " says hello.\n";
    }    
};

int main()
{
    SingletonExample::get_instance().method();
    DoubletonExample::get_instance().method();
    DoubletonExample::get_instance<0>().method();
    DoubletonExample::get_instance<1>().method();
}

残念ながら、コードはまだコンパイルされていません。

/tmp/ccsFtliS.o: In function `SingletonExample& n_ton_base<SingletonExample, 1ul>::get_instance<0ul>()':
nton.cpp:(.text._ZN10n_ton_baseI16SingletonExampleLm1EE12get_instanceILm0EEERS0_v[SingletonExample& n_ton_base<SingletonExample, 1ul>::get_instance<0ul>()]+0x5): undefined reference to `n_ton_base<SingletonExample, 1ul>::instances'
/tmp/ccsFtliS.o: In function `DoubletonExample& n_ton_base<DoubletonExample, 2ul>::get_instance<0ul>()':
nton.cpp:(.text._ZN10n_ton_baseI16DoubletonExampleLm2EE12get_instanceILm0EEERS0_v[DoubletonExample& n_ton_base<DoubletonExample, 2ul>::get_instance<0ul>()]+0x5): undefined reference to `n_ton_base<DoubletonExample, 2ul>::instances'
/tmp/ccsFtliS.o: In function `DoubletonExample& n_ton_base<DoubletonExample, 2ul>::get_instance<1ul>()':
nton.cpp:(.text._ZN10n_ton_baseI16DoubletonExampleLm2EE12get_instanceILm1EEERS0_v[DoubletonExample& n_ton_base<DoubletonExample, 2ul>::get_instance<1ul>()]+0x5): undefined reference to `n_ton_base<DoubletonExample, 2ul>::instances'
collect2: ld gab 1 als Ende-Status zurück

私は何を間違えましたか?

4

3 に答える 3

9

Etienne Cordonnierが指摘したように、クラスstaticの代わりにローカルstaticを使用する方がはるかに簡単です。

template<typename Derived, size_t n = 1>
class n_ton_base                 // Singletons are the default
{
protected:

    // Prevent n_ton_base to be used outside of inheritance hierarchies
    n_ton_base() {} 

    // Prevent n_ton_base (and Derived classes) from being copied
    n_ton_base(const n_ton_base&) = delete;

public:
                   // Get first element by default, useful for Singletons
    template<size_t i = 0>
    static Derived& get_instance()
    {
        static_assert(i < n, "Time to increase n it seems!");

        static Derived instance;
        return instance;
    }
};

インスタンス化された各メンバー関数には独自のローカル静的関数があるため、配列は必要ありません。

これにより、何もしなくてもスレッドセーフなレイジー初期化が実現します。良い!

于 2013-02-02T15:25:30.910 に答える
8

これをグローバルスコープで追加します。

template<typename Derived, size_t n>
Derived n_ton_base<Derived, n>::instances[n + (n == 0)];

ところで、std::array<>ゼロサイズの配列を許可するので、それを検討することをお勧めします。

于 2013-02-02T14:11:18.850 に答える
1

クラス静的メンバーについての説明はここにあります:

静的データメンバー(C ++のみ):

クラスのメンバーリストでの静的データメンバーの宣言は定義ではありません。名前空間スコープで、クラス宣言の外部で静的メンバーを定義する必要があります。例えば:

class X {
public:
    static int i;
};

int X::i = 0; // definition outside class declaration

したがってn_ton::instances、クラスの外部で定義する必要があります。

于 2013-02-02T14:16:11.063 に答える