Допустим класс содержит в себе контейнер объектов, причем, сам контейнером в узком смысле не является. Например -- класс, хранящий и выдающий дескрипторы открытых файлов, и предоставляющий дополнительные операции над ними. Как лучше предоставить средства для получения списка значений внутреннего контейнера?
Пример
class X {
public:
typedef std::vector<std::string> container;
private:
container c;
};
Есть еще подходы?
Что делать если внутренний контейнер не std::vector<std::string>, а std::map<int, Z>, где Z — структура, из которой мы хотим выдавать лишь одно поле, а не всю структуру? Для этого подходит второй способ, но функцию приходится определять сразу, то есть в hpp-файле. Есть какое нибудь стандартное решение?
Здравствуйте, Аноним, Вы писали:
А>Что делать если внутренний контейнер не std::vector<std::string>, а std::map<int, Z>, где Z — структура, из которой мы хотим выдавать лишь одно поле, а не всю структуру? Для этого подходит второй способ, но функцию приходится определять сразу, то есть в hpp-файле. Есть какое нибудь стандартное решение?
Поскольку объявление члена — container c — всё равно лежит в хедере, то не вижу препятствий, чтобы там же лежало и определение функции.
Оно несложное
template<class OutIt>
void copy(OutIt out)
{
std::transform(c.begin(), c.end(), out, theFieldOfZ);
}
// не хочу городить bind в ущерб читаемостиstatic int justFieldOfZ(std::map<int,Z>::value_type const& elem)
{
return elem->second.theField;
}
Здравствуйте, Кодт, Вы писали:
К>Поскольку объявление члена — container c — всё равно лежит в хедере, то не вижу препятствий, чтобы там же лежало и определение функции. К>Оно несложное К>
Здравствуйте, Wody, Вы писали:
W>Спасибо, приятное решение. А как поступить если для X используется подход с разделением на интерфейс (абстрактный класс) и имплементацию?
А саму функцию несложно сконструировать из итератора
struct writer // всеядная функция - мономорфный тип с полиморфным оператором
{
typedef void result_type;
template<class I, class V> void operator()(I& i, V const& v) { *i++ = v; }
};
std::vector<long> vec; // заметим, что тип приёмника (long) не обязательно совпадает с типом источника (int)
x.copyTo( boost::bind(writer(), std::back_inserter(vec), _1) );
К>А саму функцию несложно сконструировать из итератора К>
К>struct writer // всеядная функция - мономорфный тип с полиморфным оператором
К>{
К> typedef void result_type;
К> template<class I, class V> void operator()(I& i, V const& v) { *i++ = v; }
К>};
К>std::vector<long> vec; // заметим, что тип приёмника (long) не обязательно совпадает с типом источника (int)
К>x.copyTo( boost::bind(writer(), std::back_inserter(vec), _1) );
К>
Погорячился: сперва back_inserter превращает push_back в итератор, а затем writer превращает его обратно в функцию.
Можно сократить
2 функции (или 3)
функция, выдающая кол-во этих объектов
и функция (или 2), выдающая константную ссылку (и неконстантную) на N-ый объект.
Похоже что все рехнулись на этих контейнерах, итераторах и темплейтах.
> Что делать если внутренний контейнер не std::vector<std::string>, а > std::map<int, Z>, где Z — структура, из которой мы хотим выдавать лишь > одно поле, а не всю структуру?
Это дело реализации этого твоего класса, а не его интерфейса.
Для этого подходит второй способ, но > функцию приходится определять сразу, то есть в hpp-файле. Есть какое > нибудь стандартное решение?
Это вовсе не обязательно. Тебе не нужен шаблонный метод копирования,
тип данных в твоём массиве вполне конкретный.