Я думаю, что мне нужна функция друга шаблона в обычном классе. Эта функция будет выполнять некоторое сложное распределение в разделяемой памяти и некоторые другие операции над аппаратным обеспечением и ОС. Но я исключил все это, чтобы показать, что проблема связана с аспектами шаблонов и / или друзей, а не с чем-то более зловещим. Основная часть заключается в том, что мне нужно, чтобы экземпляр класса и его данные-члены были распределены с помощью распределителя, который я могу передать в качестве универсального параметра.
class Foo {
public:
const long * const larry;
const long * const curly;
const long * const moe;
private:
Foo() : larry(0), curly(0), moe(0) {}; // not used
Foo(long * _larry, long * _curly, long * _moe) :
: larry(_larry), curly(_curly), moe(_moe)
{
// some unrelated memory management and OS stuff happens here
}
template<class Alloc> friend const Foo * alloc_Foo(long count);
public: // factories
template<class Alloc> const Foo * factory_A(long);
// template<class Alloc> const Foo * factory_B(long);
// ...
// template<class Alloc> const Foo * factory_G(long);
};
template<class Alloc> const Foo * alloc_Foo(long count)
{
typename Alloc::template rebind<long>::other a_long;
// allocate internal parts in shared memory
const long * const larry = a_long.allocate(count+2);
const long * const curly = a_long.allocate(count+44);
const long * const moe = a_long.allocate(count*3);
Alloc alloc;
const Foo * const p_foo = alloc.allocate(1);
alloc.construct(p_foo, Foo(larry, curly, moe));
);
Я думаю, что это должно быть правильным решением. Только alloc_Foo должен вызывать конструктор, и только фабричные методы должны вызывать alloc_Foo. Экземпляр Foo и его отдельно выделенные внутренние части создаются в разделяемой памяти, где они должны быть, а все сложные элементы размещения скрыты в шаблоне alloc_Foo Friend. Эту часть я могу заставить работать нормально. Я даже не против иметь реализацию alloc_Foo в одном и том же файле, потому что он короткий и простой. Но фабрики, которые вызывают alloc_Foo, являются большими и сложными и могут загромождать простой и понятный класс с десятками включений и многими сотнями строк кода.
Я попытался включить реализации в конце, чтобы у меня была каждая фабрика в отдельном файле.
#include "factory_A.tpp"#include "factory_B.tpp"// etc.
Затем в файлы .tpp я помещаю фактический код, но я не могу ничего включить, скажем, bar.h, там. Правила #include, кажется, рушатся. Боюсь, что это как-то связано с моим другом-распределителем шаблонов. Я бы очень не хотел потерять это, так как это решает многие другие мои проблемы.
../blah/blah/factory_A.tpp:10:9: error: 'Bar' was not declared in this scope
make: *** [blah/blah/main.o] Error 1
Обычно я не был бы настолько одержим соглашением о прицеле, но это необычная комбинация для меня. Может быть, я обдумываю всю сделку. Я считаю, что alloc_Foo должен быть другом, чтобы он мог видеть конструкторов, которые я скрываю. Я считаю, что он также должен быть частным и что только фабрики должны иметь возможность использовать его. Я считаю, что как распределитель, так и фабрики на самом деле не являются частью этой функции. У них нет или не нужно «это». Может быть, они должны быть статичными. Я полагаю, что это должен быть шаблон, потому что мне нужно использовать специальный распределитель для многих внутренних частей и сам объект для каждого экземпляра. Должно ли это быть статичным.
Кто-нибудь может помочь?
Благодарю.
Я уверен, что это не имеет ничего общего с шаблонами или друзьями. Препроцессор знает ничего такого Что касается шаблонов или друзей, он просто открывает файлы и вставляет их содержимое в другие файлы, шаблоны и друзья не могут «заставить правила включения распадаться». То, что вы делаете, должно быть хорошо.
Проверьте включение охранников на bar.h
они такие же, как другие файлы?
Ты #include "factory_A.tpp"
в то время как некоторое пространство имен открыто? Попробуйте закрыть пространство имен перед тем, как добавить дополнительные элементы внизу файла.
Или Bar
в некотором пространстве имен, и вы должны сказать, x::Bar
?
Вы ошибаетесь bar.h
? Попробуйте переименовать файл заголовка во что-то другое, что-то отличительное, что не будет вызываться другой заголовок, и измените #include
к этому.
Если ничего из этого не работает, уменьшите код до минимального полный пример, который воспроизводит проблему. В настоящее время вы не показываете достаточно кода, чтобы увидеть, где настоящая проблема, но это почти наверняка не то, что вы предложили, а где-то еще в коде, который вы не показали.
Других решений пока нет …