Переполнение стека. Помогите!
P.S. Это код объявления шаблона класса id_node (наследника шаблона класса id_node_com) и две его конкретные специализации для параметра-типа (id_one_table) и параметра-шаблона (id_node<id_one_table>)...
{
public:
id_node(UnicodeString table_name, UnicodeString p_id, UnicodeString p_table, bool inf_store=false, UnicodeString f_names="", UnicodeString f_one_names="", UnicodeString f_two_names="", UnicodeString f_one_1_names="", UnicodeString f_one_2_names="");
};
template <> class id_node<id_one_table>: public id_node_com<id_one_table>
{
public:
id_node(UnicodeString table_name, UnicodeString p_id, UnicodeString p_table, bool inf_store=false, UnicodeString f_names="", UnicodeString f_one_names="", UnicodeString f_two_names="", UnicodeString f_one_1_names="", UnicodeString f_one_2_names="");
void load(bool def=false);
};
template <> class id_node<id_node<id_one_table> >: public id_node_com<id_node<id_one_table> >
{
public:
id_node(UnicodeString table_name, UnicodeString p_id, UnicodeString p_table, bool inf_store=false, UnicodeString f_names="", UnicodeString f_one_names="", UnicodeString f_two_names="", UnicodeString f_one_1_names="", UnicodeString f_one_2_names="");
void load(bool def=false);
};
Может быть вы подскажете как в шаблоне:
организовать создание экземпляров класса T, если они могут иметь РАЗНЫЕ конструкторы?
Хм. Странно, но если меняю объявление
{
public:
...
};
например на
{
public:
...
};
то все запускается нормально...
{
typedef std::vector<UnicodeString *> StrTab;
typedef std::deque<UnicodeString> StrQueue;
typedef std::pair<int, id_memorandum_types::StrTab *> Id_Obj;
};
class id_memorandum
{
protected:
int id_count;
int field_count;
UnicodeString field_names;
bool information_store;
std::map<int, id_memorandum_types::StrTab *> ids;
public:
id_memorandum(bool inf_store=false, UnicodeString f_names="");
bool add_id(int id, id_memorandum_types::StrTab *id_string);
bool del_id(int index);
id_memorandum_types::Id_Obj get_id(int index);
id_memorandum_types::Id_Obj find_id(int id);
int count();
};
class id_one_table:public id_memorandum
{
protected:
UnicodeString table,id_name,parent_id,parent_table,parent_id_name;
public:
id_one_table(UnicodeString table_name, UnicodeString p_id, UnicodeString p_table, bool inf_store=false, UnicodeString f_names="");
bool add_record(UnicodeString fields, UnicodeString values);
sh_core::query_table *get_record(int index, UnicodeString fields);
bool set_record(int index, UnicodeString fields_and_values);
bool del_record(int index);
void empty();
void load(bool del=false);
};
Вот минимальный код с подобной ошибкой (компилировал на "Embarcadero C++ Builder 2010 XE 15.0.3890.34076"): при запуске это рушится с ошибкой переполнения стека... (на Visual C++ не компилируется с ошибкой
"123321.cpp(21): error C2244: BigErrorHere<int>::{ctor}: не удается сопоставить определение функции существующему объявлению
определение
'BigErrorHere<int>::BigErrorHere(char)'
существующие объявления
'BigErrorHere<int>::BigErrorHere(const BigErrorHere<int> &)'
'BigErrorHere<int>::BigErrorHere(char)'" - полагаю здесь где-то explicit использовать надо? Объявление всех конструкторов с explicit результата не принесло...)
{
public:
BigErrorHere(char hello) {};
};
template<> class BigErrorHere<int>
{
public:
BigErrorHere(char hello);
};
template<class T> BigErrorHere<int>::BigErrorHere(char hello)
{};
BigErrorHere<int> Bug('X');
Причем нижеприведенный код запускается нормально...
{
public:
BigErrorHere(char hello) {};
};
template<> class BigErrorHere<int>
{
public:
BigErrorHere(char hello) {};
};
BigErrorHere<int> Bug('X');
Эй, короче... Я так понимаю у каждого компилятора свои замуты со специализацией шаблонов. Просто сделал определение конструкторов внутри объявления класса и все заработало (explicit не помог - была все та же stack overflow). И это не смотря на то, что остальные методы я все же определяю отдельно. Кстати, компилятор Builder'a не указал на ошибку и просто вывалился со странной stackoverflow (я, дурак, полтора дня рекурсию искал) при запуске, а компилятор Visual C++ указал на ошибку. Судите о качестве компиляторов, Господа!
Ссылки по теме, может кому пригодятся...
msdn.microsoft.com - здесь говорится, что нельзя специализировать шаблон функции частично.
stackoverflow.com - а здесь парень выкрутился аналогичным способом.
Чтобы специализировать шаблон класса, следует объявить класс, предварив его конструкцией template<>, и указать типы, для которых специализируется шаблон класса. Типы используются в качестве аргументов шаблона и задаются непосредственно после имени класса.
template <> class Stack<std::string>
{
void push(std::string const& elem);
...
}
Для таких специализаций любая функция-член должна определяться как "обычная" функция-член с заменой каждого включения Т специализированным типом.
void Stack<std::string>:: push(std::string const& elem)
{
elems.push_back(elem); // Добавление копии элемента в конец массива
}
Как видно из этой цитаты "бажный" кусок кода:
{
public:
BigErrorHere(char hello) {};
};
template<> class BigErrorHere<int>
{
public:
BigErrorHere(char hello);
};
template<class T> BigErrorHere<int>::BigErrorHere(char hello)
{};
BigErrorHere<int> Bug('X');
исправляется удалением template<class T> из объявления конструктора:
{
public:
BigErrorHere(char hello) {};
};
template<> class BigErrorHere<int>
{
public:
BigErrorHere(char hello);
};
BigErrorHere<int>::BigErrorHere(char hello)
{};
BigErrorHere<int> Bug('X');
Как геморройна жизнь начинающего...
Ссылки по теме, может кому пригодятся...
msdn.microsoft.com - здесь говорится, что нельзя специализировать шаблон функции частично.
А я не увидел у вас функций, только классы. Хотя может среди того месива кода и есть, у меня тоже глаза ломаются смотреть :)