LINUX.ORG.RU

Форсировать линковку статических членов класса

 


0

1

Доброго всем. Хочется такого изврата: есть некий класс, он может содержать несколько статических полей (объектов), причем в объектах важна только работа конструктора (регистрация объекта в статическом же векторе), кроме создания этих объектов они больше могут нигде не использоваться. Если «забыть» описать один из таких объектов в .cpp - линковщик молча проглотит (и в общем-то будет прав - зачем нужен объект, который никем не используется?). Как заставить его насильно референсить такие объекты? Типа такого:

class Foo
{
public:
    static const MyObject Bar;
    static const MyObject Baz;
};

const MyObject Foo::Bar;
// const MyObject Foo::Baz; // допустим забыли это написать. Надо чтобы компилер/линкер дал по рукам

Решения для C++11 и GCC-only - подходят.

★★★★★

Последнее исправление: dib2 (всего исправлений: 2)

кроме создания этих объектов они больше могут нигде не использоваться.

Зачем ими тога светишь в определии класса? Засунул бы статиком внтури cpp файла, будет всего одна строчка для каждого объекта.

mashina ★★★★★
()

Ммм... От совсем беспроглядной забывчивости вряд ли можно спасти.

Как насчёт такого варианта?

// BarBazzed.h
template <class T>
class BarBazzed
{
public:
    static const MyObject Bar;
    static const MyObject Baz;
};

template <class T>
const MyObject BarBazzed<T>::Bar;

template <class T>
const MyObject BarBazzed<T>::Baz;


// Foo.h
class Foo : public BarBazzed<Foo>
{
    // ...
};

ilammy ★★★
()
Ответ на: комментарий от mashina

когда они не используется из-вне - это частный случай. Видимость за пределами единицы трансляции тоже нужна (и желательно в рамках класса, а не глобально).

пробовал __attribute__((used)) в разных позах - не помогает(

dib2 ★★★★★
() автор топика
Ответ на: комментарий от dib2

От терминальной забывчивости (забыл написать : public BarBazzed<Foo>) не спасает, но если всё же написать, то в cpp-файле ничего не надо упоминать.

ilammy ★★★
()
Ответ на: комментарий от ilammy

А, не, отбой. В таком виде не взлетит. Надо ещё template class BarBazzed<Foo>; в хедере прописывать, чтобы заставить проинстанциировать шаблон.

ilammy ★★★
()
Ответ на: комментарий от ilammy

но при этом инстанциировать он его будет в каждом .cpp где надо, и линкер пошлет такие объектники.

ладно, в свете того, что static - это вообще зло и почти ненужно, буду изобретать другой дизайн.

dib2 ★★★★★
() автор топика
namespace
{

class Bar {
...
};

class Bar bar = Bar(...);

class Baz {
...
};

class Baz baz = Baz(...);

} //namespace

class MyObject
{
  const class Bar &bar;
  const class Baz &baz;
  public:
    MyObject() :bar(bar), baz(baz) {}
};
nanoolinux ★★★★
()
Ответ на: комментарий от dib2

Да вроде при явном инстанциировании шаблонов для них код только один раз генерируется.

ilammy ★★★
()

Напоминает реализацию фабрики и тем не менее то, что вы делаете — зло, и вот почему:

1) линкер не увидел, а программист тем более пропустит 2) магические side-effects, т.к. 3) неопределённый неявный порядок вызова конструкторов и (!) деструкторов 4) глобальные переменные — особое зло, нужное только в эксклюзивных случаях, и должное быть задокументировано.

В больших проектах дебажить такое, развивать и использовать — это боль умноженая в десятки раз...

exhu
()
Ответ на: комментарий от anonymous

очень приятно получить такой глубокий и профессиональный комментарий, спасибо

dib2 ★★★★★
() автор топика

причем в объектах важна только работа конструктора (регистрация объекта в статическом же векторе

Вот пусть твой статический вектор и создаёт сам себе объекты, можно даже явно.

legolegs ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.