И мы пишем к ней юнит-тесты. Тогда в тестах логичен такой код:
// Функция-хелпер: извлечь категории и проверить их соответствие переданному списку
CheckCategoriesExtraction(const Film& film, const vector<Category>& categories);
CheckCategoriesExtraction(AvatarMovie, список_категорий_Аватара);
CheckCategoriesExtraction(TitanicMovie, список_категорий_Титаника);
Беда в том, что C++ не позволяет передать в функцию набор значений вектора. Более того, этого не позволяет даже Boost Assign. А С++0x, где это обещается, пока не вышел...
Для решения проблемы я написал небольшой класс, по которому ищу обратную связь.
Класс такой:
template<typename T>
class Enum
{
typedef vector<T> Container;
Container m_data;
public:
Enum() {}; // makes empty vector
// Non-explicit - can create Enum by single value
Enum(T t1)
{
m_data.push_back(t1);
}
// Several elements ctors
Enum(T t1, T t2)
{
m_data.push_back(t1);
m_data.push_back(t2);
}
Enum(T t1, T t2, T t3)
{
m_data.push_back(t1);
m_data.push_back(t2);
m_data.push_back(t3);
}
// several other constructors... //
size_t size() const
{
return m_data.size();
}
void push_back(const T& t)
{
m_data.push_back(t);
}
T& operator[](size_t i)
{
if (i >= m_data.size())
throw std::out_of_range("Enum<> operator[] bad index!");
return m_data[i];
}
// For easy assigningoperator Container()
{
return m_data;
}
};
Соответственно, класс позволяет использовать такие конструкции:
typedef Enum<Category> Categories;
CheckCategoriesExtraction(AvatarMovie, categFantastic); // one category only - no need of Enum
CheckCategoriesExtraction(TitanicMovie, Categories(categHistoric, categDrama));
CheckCategoriesExtraction(EmptyMovie, Categories()); // film w/o categories
vector<Category> categoriesIlike = Categories(categAction, categComedy);
vector<int> valuesToCheck = Enum<int>(1, 4, 9, 15);
Преимущества:
1. Просто и удобно.
2. Легко встраивать в имеющийся код (за счет создания Enum'а по одному значению и автоматического присвоения обычному вектору).
Вопросы:
1. Какие существуют аналогичные решения? (в рамках известных библиотек, типа Boost/Loki)
2. Как можно упросить код, связанный с определением конструкторов? (чтобы не писать конструктор под каждый размер)
3. Идеи по улучшению и развитию класса? (если делать его универсальным, для использования не только мною)
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>Вопросы:
B>1. Какие существуют аналогичные решения? (в рамках известных библиотек, типа Boost/Loki) B>2. Как можно упросить код, связанный с определением конструкторов? (чтобы не писать конструктор под каждый размер) B>3. Идеи по улучшению и развитию класса? (если делать его универсальным, для использования не только мною)
Предлагаю свою щестеренку в ваш велосипед.
Enum& operator<<(const T& t)
{
push_back(t);
return *this;
}
Здравствуйте, Basil2, Вы писали:
B>Для решения проблемы я написал небольшой класс, по которому ищу обратную связь.
коротко: класс не нужен
решения:
классика http://ideone.com/pwstw
драфт http://ideone.com/SnwU7
Здравствуйте, Basil2, Вы писали:
B>этого не позволяет даже Boost Assign.
В смысле — не позволяет?
Передавай assign::list_of в эту функцию вместо вектора, всего делов.
...
C>Предлагаю свою щестеренку в ваш велосипед. C>Enum& operator<<(const T& t) C> { C> push_back(t); C> return *this; C> }
C>и тогда
C>vector<int> valuesToCheck = Enum<int>()<<1<<4<<9<<15;
Ваша шестерёнка заменила весь двигатель
И ещё, я бы использовал наследование.
template <typename T>
class vector_init: public vector<T>
{
public:
vector_init(int n = 0) { if (n > 0) reserve(n);} // необязательный момент оптимизации
vector_init& operator <<( const T& _Val ) { this->push_back(_Val); return *this;} // в этом методе хорошо бы добавлять только не уникальный _Val
};
DF>И ещё, я бы использовал наследование.
DF>template <typename T> DF>class vector_init: public vector<T> DF>{ DF>public: DF> vector_init(int n = 0) { if (n > 0) reserve(n);} // необязательный момент оптимизации DF> vector_init& operator <<( const T& _Val ) { this->push_back(_Val); return *this;} // в этом методе хорошо бы добавлять только не уникальный _Val DF>};
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Basil2, Вы писали:
B>>Для решения проблемы я написал небольшой класс, по которому ищу обратную связь. U>коротко: класс не нужен U>решения: U>классика U>http://ideone.com/pwstw
Прикольный способ
Однако, как я понимаю, там всегда необходимы 2 строчки кода, а не одна?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, Basil2, Вы писали:
B>>этого не позволяет даже Boost Assign. J>В смысле — не позволяет? J>Передавай assign::list_of в эту функцию вместо вектора, всего делов.
Ммм..., тоже верно
Наверное, мне синтаксис этого list_of()()() не понравился, когда я на него смотрел
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, collider, Вы писали:
B>>3. Идеи по улучшению и развитию класса? (если делать его универсальным, для использования не только мною)
C>Предлагаю свою щестеренку в ваш велосипед. C>Enum& operator<<(const T& t) C> { C> push_back(t); C> return *this; C> } C>и тогда C>vector<int> valuesToCheck = Enum<int>()<<1<<4<<9<<15;
Кстати, это навевает идею для решения другой проблемы юнит-тестов (и не только).
Пусть есть такой код:
const char *url;
if (shitHappend)
{
string errMsg = string("Shit happpend: on url ") + url;
throw exception(errMsg.c_str());
}
Или:
int errorCode;
if (shitHappend)
{
stringstream str;
str << "Shit happpend: on url " << url << " errcode=" << errorCode;
throw exception(str.str().c_str());
}
Многовато кода для обработки одной ошибки, IMHO.
Хочется видеть более короткое решение, типа:
if (shitHappend)
throw exception("Shit happpend: on url " + url + " errcode=" + errorCode);
Или хотя бы:
if (shitHappend)
throw exception(Msg()<<"Shit happpend: on url "<<url<<" errcode="<<errorCode);
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>Преимущества: B>1. Просто и удобно. B>2. Легко встраивать в имеющийся код (за счет создания Enum'а по одному значению и автоматического присвоения обычному вектору).
Вот жаль проблема надуманая, неужели мы будем категории писать в C++?
Даже если это Unit test тогда можно не заморачиваться и написать пару раз push_back вместо того, что бы..... писать еще один юнит тест на эту поделку
З.Ы. если уж так сильно хочеться
предлагаю переопределить оператор +.
И завести два класса, Контейнер Категорий и просто категории.
Здравствуйте, IROV.., Вы писали:
IRO>Вот жаль проблема надуманая, неужели мы будем категории писать в C++? IRO>Даже если это Unit test тогда можно не заморачиваться и написать пару раз push_back вместо того, что бы..... писать еще один юнит тест на эту поделку
Пару?? Даже в приведенном примере требуется минимум 5 push_back, а таких тестов в коде десятки!
IRO>предлагаю переопределить оператор +. IRO>И завести два класса, Контейнер Категорий и просто категории.
Идея интересная, оператор+ складывает два класса и возвращает вектор
А как быть, если категория одна или их нет?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, _nn_, Вы писали:
__>Boost.Exception ?
Boost.Exception несколько про другое. Добавление predefined типов мне излишне, равно как необходимоть их определения.
Потом, подобный класс может использоваться не только в исключениях, например:
LogError(Msg() << "Shit happend: " << errorCode);
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Здравствуйте, Basil2, Вы писали:
B>Пару?? Даже в приведенном примере требуется минимум 5 push_back, а таких тестов в коде десятки!
А как ты их используешь в "рабочем" коде?
IRO>>предлагаю переопределить оператор +. IRO>>И завести два класса, Контейнер Категорий и просто категории. B>Идея интересная, оператор+ складывает два класса и возвращает вектор B>А как быть, если категория одна или их нет?
У контейнера конструктор на одну категорию, и также пустой конструктор.
Лучше, отсутсвие категории — делать перегрузкой функции/создать спец функцию w\o
Здравствуйте, Basil2, Вы писали:
B>Здравствуйте, _nn_, Вы писали:
__>>Boost.Exception ? B>Boost.Exception несколько про другое. Добавление predefined типов мне излишне, равно как необходимоть их определения.
B>Потом, подобный класс может использоваться не только в исключениях, например: B>