Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > инициализация статических данных


Автор: zss 3.7.2006, 09:18
есть шаблонный класс

Код

template <typename T>
class Parser {
private :
    Parser (const Parser&);
    Parser& operator = (const Parser&);

protected :
    typedef std::map <T, std::string> Map;
    typedef typedef Map::const_iterator ItMap;
    static const Map map_;

public :
    Parser () {;}
    virtual ~Parser () {;}

    static T ToValue (const std::string& string);
    static std::string ToString (T value);
};



я хочу наследоваться от него и просто инициализировать map_;

например *.h
Код

enum ENUM
{
   a,
   b,
   c
   ...
}

class Some : Parser<ENUM> {};


и тогда 
*.cpp
Код

const Parser<ENUM>::Map Some::Parser::map_ = boost::assign::map_list_of(a, "a")(b, "b")(c, "c");


но
1. Говорит, что нельзя инициализировать статические члены через производный класс
2. каждый шаблон будет инстанцирован со своим статическим map_? 

например
Код

class Some1 : Parser<ENUM> {};
class Some2 : Parser<ENUM> {};
...
const Parser<ENUM>::Map Some1::Parser::map_ = boost::assign::map_list_of(a, "a")(b, "b")(c, "c");
const Parser<ENUM>::Map Some2::Parser::map_ = boost::assign::map_list_of(a, "a")(b, "b")(c, "c");


3.и как будет дело обстоять с однотипными шаблонами (тоесть инстанцированные одним типом) 

например
Код

class Some1 : Parser<ENUM1> {};
class Some2 : Parser<ENUM2> {};
...
const Parser<ENUM1>::Map Some1::Parser::map_ = boost::assign::map_list_of(a, "a")(b, "b")(c, "c");
const Parser<ENUM2>::Map Some2::Parser::map_ = boost::assign::map_list_of(a, "a")(b, "b")(c, "c");

 

Автор: slava72 3.7.2006, 11:07
т.к. map_ принадлежит Parser<ENUM> то и инициализировать нужно Parser<ENUM>::map_

соответствено, все классы порожденные от Parser<ENUM> будут разделять 1 и тот же map_, а
Parser<ENUM1>::map_ и  Parser<ENUM2>::map_ - различны 

Автор: zss 3.7.2006, 11:25
Цитата(slava72 @  3.7.2006,  11:07 Найти цитируемый пост)
соответствено, все классы порожденные от Parser<ENUM> будут разделять 1 и тот же map_, а
Parser<ENUM1>::map_ и  Parser<ENUM2>::map_ - различны  


спасибо - понятно (главное что для разных ENUM разные map_)


Цитата(slava72 @  3.7.2006,  11:07 Найти цитируемый пост)
т.к. map_ принадлежит Parser<ENUM> то и инициализировать нужно Parser<ENUM>::map_


пробовал
Код

const Parser<ENUM>::Map Some::Parser<ENUM>::map_ = ...;


таже фигня  

Автор: slava72 3.7.2006, 12:04
а так ?
Код

const Parser<ENUM>::Map Parser<ENUM>::map_ = ...
 

вообще то для подобных конструкций предпочитаю пользоватся typedef-ом )) 

Автор: zss 3.7.2006, 12:19
Цитата(slava72 @  3.7.2006,  12:04 Найти цитируемый пост)
а так ?

тоже самое


Цитата(slava72 @  3.7.2006,  12:04 Найти цитируемый пост)
вообще то для подобных конструкций предпочитаю пользоватся typedef-ом )) 


Map и есть typedef
Код

    typedef std::map <T, std::string> Map;
    typedef typedef Map::const_iterator ItMap;
 

Автор: slava72 3.7.2006, 12:50
Выдержка из draft-a:

Цитата

14.5.1.3 Static data members of class templates [temp.static]
1 A definition for a static data member may be provided in a namespace scope enclosing the definition of the static
member’s class template. [ Example:
template < class T > class X {
static T s;
};
template < class T > T X<T >::s = 0;


Не до конца понятно, но похоже инитить чем хочешь не получится. Обмануть можно чем то вроде:
Код

template <typename T> struct TypeOfMapInit {};

template <typename T>
std::map <T, std::string> InitMap(TypeOfMapInit<T>); 
// обявляем шаблонную функцию для инициализации

template <typename T>    
class Parser {
...
};
template<class T> const Parser<T>::Map Parser<T>::_map = InitMap(TypeOfMapInit<T>());
// инициализируем вызовом шаблонной функции

// специализируем инициализатор
template<>
std::map < ENUM, std::string>  InitMap(TypeOfMapInit< ENUM>) {
  return boost::assign::map_list_of(a, "a")(b, "b")(c, "c");
}


Что-то типа этого, но не уверен что прокатит ((

либо (для сокрытия деталей) в классе Some1 объявляем статическую функцию, возвращающюю map
(можно приватню - тогда объявляем InitMap другом), в специализации InitOfMap - вызываем эту статическую функцию. Реализация функции в .cpp

  

Автор: slava72 3.7.2006, 13:14
Еще 1-н вариант (не знаю насколько удобный/удачный) в этой задаче - шаблонс с 2-мя параметрами,
при этом 2-й - указатель на функцию. Хотя не совсем ясен прототип этой функции. Компилера под рукой нет, но что-то подобное:

Код


template<class T, std::map<T> (*F)()>
class Parser {    
...    
};    
template<class T, std::map<T> (*F)()>
const Parser<T>::Map Parser<T>::_map = F();

 

Автор: zss 3.7.2006, 14:42
slava72, вот так компилится

Код

template <>
const Some::Parser<ENUM>::Map Some::Parser<ENUM>::map_ = ...


но я не совсем уверен, что это правильно

и еще не линкуется - говорит, что не видно ToString и ToValue 

Автор: slava72 3.7.2006, 15:06
Если компиоится, то все нормально, по идее номальная специализация.

А ToString и ToValue похоже надо писать самому - это преобразование класса <T> в стороку и обратно. 

В .cpp:

Код

template <>
ENUM Parser<ENUM>::ToValue (const std::string& string) {
  ...
}

template <>
std::string Parser<ENUM>::ToString (ENUM value) {
  ...
}

  

Автор: zss 3.7.2006, 15:10
Цитата(slava72 @  3.7.2006,  15:06 Найти цитируемый пост)
А ToString и ToValue похоже надо писать самому - это преобразование класса <T> в стороку и обратно. 


тогда пропадает весь смысл шаблонного наследования smile
 

Автор: slava72 3.7.2006, 15:37
Цитата

тогда пропадает весь смысл шаблонного наследования 


Если шаблонные функции вызываются, значит их кто-то должен написать ? smile 

Можно наложить ограничения на шаблонный параметр, например считать 
T - классом, имеющим конструктор от строки и преобразование в строку.
Или дружественные функции string ToString(const T&) или еще что нибудь.

Для этих типов пишешь обобщенную реализацию функций.
А для всех не удовлетворяющих - специализированные функции.

Опять таки вопрос - кто автор класса Parser - если ты сам, то нужно более детально продумать что и как ты хочешь сделать. А если кто-то другой, то есть что дают ... smile  

Автор: zss 3.7.2006, 15:44
Цитата(slava72 @  3.7.2006,  15:37 Найти цитируемый пост)
Если шаблонные функции вызываются, значит их кто-то должен написать ?



все оказалось проще - у меня реализация была описана в *.cpp - перенес в *.h и все сварилось smile

спасибо за помощь 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)