Здравствуйте, Аноним, Вы писали:
А>Есть такой метод:
А>template <class _ValueType> А>bool GetValue(const std::string& value_name, _ValueType& value);
А>_ValueType — может быть как простым значением так и контейнером.
Кстати, так как у всех STL-контейнеров определен тип value_type, то можно сделать что-нть вроде (в таком виде не скомпилируется, но идея, думаю, понятна):
template<typename ValueType>
void GetValue( long id, ValueType& value ) {}
template<typename ValueType>
void GetValue( long id, std::vector<ValueType>& value ) {}
Здравствуйте, Аноним, Вы писали:
А>Подскажите, как определить _ValueType контейнер или нет???
Что известно о контейнере кроме того, что он должен иметь функцию push_back ?
А>Понятно, что этот метод можно разбить на 2, GetValue и GetValues... но не хочется.
Вряд ли удастся совместить в одной функции строки
value.push_back(FromString(*it));
value = FromString(strValue);
Любите книгу — источник знаний (с) М.Горький
Re[2]: Как отличить контейнер от простого значения?
От:
Аноним
Дата:
12.10.07 13:31
Оценка:
SI>
SI>template<typename ValueType>
SI>void GetValue( long id, ValueType& value ) {}
SI>template<typename ValueType>
SI>void GetValue( long id, std::vector<ValueType>& value ) {}
SI>
SI>как вариант?
Вариант не подходит, т.к в качестве контейнера может быть еще deque (из-за проблем vector<bool>) или list. Обязательное условие для контейнера наличие метода push_back.
Re[2]: Как отличить контейнер от простого значения?
От:
Аноним
Дата:
12.10.07 13:45
Оценка:
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, Аноним, Вы писали:
А>>Подскажите, как определить _ValueType контейнер или нет??? B>Что известно о контейнере кроме того, что он должен иметь функцию push_back ?
фактически в качестве контейнеров пока используются только list, deque и vector.
Кроме push_back аграничений пока нет.
А>>Понятно, что этот метод можно разбить на 2, GetValue и GetValues... но не хочется. B>Вряд ли удастся совместить в одной функции строки B>
template<typename ValueType>
void GetValue( long id, ValueType& value ) {}
template<typename ValueType, typename Allocator>
void GetValue( long id, std::vector<ValueType, Allocator>& value ) {}
---
а в целом по топику могу сказать что не знаю пока способа лучще чем сделать метафункцию is_std_container и явно специализировать ее для всех STL контейнеров -- благо их оч небольшое число
и тогда:
template <typename ValueType>
typename boost::enable_if<
is_std_container<ValueType>
> GetValue(long id, ValueType& value)
{
// тут код для случая когда value является контейнером
}
template <typename ValueType>
typename boost::enable_if<
boost::mpl::not_<is_std_container<ValueType> >
> GetValue(long id, ValueType& value)
{
// тут код для случая когда value не является конетйнером
}
какнить так
Re[3]: Как отличить контейнер от простого значения?
Здравствуйте, Аноним, Вы писали:
А>Да, видимо придется специализировать для контейнеров. Но для каждого отдельного контейнера добавлять специализацию не охота...
Ну заведи себе что-нибудь типа
template<typename TContainer> struct ContainerRef {
TContainer& Ref;
ContainerRef( TContainer& ref ) : Ref( ref ) {}
};
template<typename T> T& tryGetAsContainer( T& t ) { return t; }
template<typename T> ContainerRef< std::vector<T> > tryGetAsContainer( std::vector<T>& t ) { return t; }
template<typename T> ContainerRef< std::list<T> > tryGetAsContainer( std::list<T>& t ) { return t; }
// и т. д.
Ну и пишешь дальше:
template<typename T>void doMyFunction( T& t ) { /* реализация для скаляра*/ }
template<typename TContainer>void doMyFunction( ContainerRef< TContainer > t ) { /* реализация для контейнера*/ }
template<typename T> void MyFunction( T& t ) { doMyFunction( tryGetAsContainer( t ) ); }
Ну или с тритсами химичишь, как тут уже и писали...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как отличить контейнер от простого значения?
Здравствуйте, Аноним, Вы писали:
А>Да, видимо придется специализировать для контейнеров. Но для каждого отдельного контейнера добавлять специализацию не охота...
Можно замутить трейт для стандартных контейнеров на базе value_type, как предложил jazzer:
Здравствуйте, Аноним, Вы писали:
А>Подскажите, как определить _ValueType контейнер или нет??? А>Понятно, что этот метод можно разбить на 2, GetValue и GetValues... но не хочется.
Настоятельно советую посмотреть в сторону паттерна Composite (см. описание у GoF). он унифицирует обработку элемента, независимо от того, одиночный это объект или коллекция.
Re[4]: Как отличить контейнер от простого значения?
А>Подскажите, как определить _ValueType контейнер или нет??? А>Понятно, что этот метод можно разбить на 2, GetValue и GetValues... но не хочется.
Как уже писал Roman Odaisky, нужно сделать 2 разных метода. Повод для этого конструкция if(){}else{}.
В обобщенном виде можно так:
template<class ValueType>
bool GetValue(const std::string& name, ValueType& value);
template<class ContainerType>
bool GetValues(const std::string& name, ContainerType& values);