Как иметь статические члены данных в библиотеке только для заголовков?

Каков наилучший способ иметь статический член в классе шаблонов без шаблонов, не ставя бремя определения члена на пользователя класса?

Скажем, я хочу предоставить этот класс:

class i_want_a_static_member
{
    static expensive_resource static_resource_;

public:
    void foo()
    {
        static_resource_.bar();
    }
};

Тогда пользователь класса не должен забывать определять статический член где-то (как уже ответил много раз):

// this must be done somewhere in a translation unit
expensive_resource i_want_a_static_member::static_resource_;

У меня есть ответ ниже, но он имеет некоторые недостатки. Есть ли лучшие и/или более элегантные решения?

Ответ 1

Вы можете использовать локальные статические переменные функции.

struct Foo {
     static int& Bar() { static int I; return I; }
}; //                    ^~~~~~~~~~~~

Ответ 2

Мое собственное решение - использовать шаблонный класс держателей, поскольку статические члены отлично работают в шаблонах и используют этот держатель в качестве базового класса.

template <typename T>
struct static_holder
{
    static T static_resource_;
};

template <typename T>
T static_holder<T>::static_resource_;

Теперь используйте класс держателя:

class expensive_resource { /*...*/ };

class i_want_a_static_member : private static_holder<expensive_resource>
{
public:
    void foo()
    {
        static_resource_.bar();
    }
};

Но поскольку имя члена указано в классе держателя, вы не можете использовать один и тот же держатель для более чем одного статического члена.