LINUX.ORG.RU

Определить контейнер ли передо мной или нет

 , , ,


0

1

Хочу накидать небольшой трансятор из стандартных контейнеров в boost::python::list.

Как лучше сделать?
Через итераторы?
Можно примерчик небольшой

★★★★★

Последнее исправление: deterok (всего исправлений: 1)
Ответ на: комментарий от CrazyAlex25

Да я все это находил, не то...

Честно говоря, я надеяля что это решается каким-нибудь общим предком или новым методом из C++11/14.

deterok ★★★★★
() автор топика

А в чём проблема перекидать в цикле через std::begin() и std::end()?

devsdc ★★
()

А как

Определить контейнер ли передо мной или нет

относится к

накидать небольшой трансятор из стандартных контейнеров в boost::python::list

?

intelfx ★★★★★
()

Не уверенн что правильно понял что именно нужно, но возможно вот этот маленький пример поможет: (шаблон функции которая выводит значения (инты но это не суть)) из заданного STL контейнера (list, set, map, vector)

#include <stdio.h>

#include <list>
#include <set>
#include <map>

template<class T>
int intVal(const T &v)
{
        return (int)(v);
}

template <class First, class Second>
int intVal(const std::pair<First,Second> &v)
{
        return (int)(v.second);
}

template<class T>
void dumpAll(const T& src, const char *id)
{
        unsigned i=0;
        for(typename T::const_iterator it=src.begin(); it!=src.end(); ++it)
        {
                i ++;
                printf("%s[%i] = %i\n", id, i, intVal(*it));
        }
        printf("\n");
}

int main(int argc, const char *argv[])
{
        std::list<int> list;
        list.push_back(11);
        list.push_back(12);
        list.push_back(13);

        std::set<int> set;
        set.insert(21);
        set.insert(22);
        set.insert(23);

        std::map<int, int> map;
        map[1] = 31;
        map[2] = 32;
        map[3] = 33;

        dumpAll(list, "List");
        dumpAll(set,  "Set");
        dumpAll(map,  "Map");

        return 0;
}

zaz ★★★★
()
Ответ на: комментарий от pon4ik

Во время компиляции. Да я уже решил как бы проблему. Написал примитивный транслятор в list.

template<class T>
list stdVectorToPyList(const vector<T> &v)
{
    list l;
    for (auto &item : v){
        l.append<decltype(item)>(item);
    }
    return l;
}

Может есть какой-нибудь вариант пошустрее или что бы заюзать boost::python::iterator?

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Чтобы работало по шустре не возвращай лист из функции а передавай по ссылке/укозателю.

template<class T>
void stdVectorToPyList(const vector<T> &v, list &l)
{
    for (auto &item : v){
        l.append<decltype(item)>(item);
    }
}
+ можно попробовать сделать l.append(v.begin(), v.end()) - если потдерживает

zaz ★★★★
()
Ответ на: комментарий от zaz

Нефига :)

Если не ошибаюсь, то здесь должна будет задействована семантика переноса. В C++11 компилятор видит, что у тебя лишний объект создается и не будет этого делать, а просто переместит существующий на место присваиваемого.

(ищи move http://habrahabr.ru/post/131478/)

deterok ★★★★★
() автор топика
Ответ на: комментарий от zaz

Итераторы не любит он. Я пытался ему кормить различные итераторы, но нет, говорит, что типы не знакомы ему. Приходится циклами перебирать простые типы...

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Не совсем, это не работает «из коробки». Для того чтобы работал перенос для сложных объектов они должны его потдерживать (реализовывать конструктор или/и оператор присвоения с rvalue-reference). В принципе все объекты из стандартной библиотеки (std) потдерживют перенос - но это совсем не означает что его потдерживает твой список (если он конечно не из stl - но и там есть свои нюансы). Если есть возможность упорядочить работу с памятью лутше делать это самому и не отдавать на откуп компилятору.

zaz ★★★★
()
Ответ на: комментарий от deterok

Ну исходная проблемма решается с помощью SFINAE.

Примерно так:

template <typename T>
class IsContainerT {
    typedef char One;
    typedef struct {char a[2];} Two;
    template<typename U> static One test(...);
    template<typename U> static Two test(typename U::value_type*, typename U::iterator*, typename U::size_type*);
public:
    enum { Yes = sizeof(IsContainerT<T>::test<T>(0, 0, 0)) != 1};
    enum { No = !Yes};
};

template <typename T> bool IsContainer(const T& t)
{
    return IsContainerT<T>::Yes;
}
pon4ik ★★★★★
()
Ответ на: комментарий от zaz

Ну вроде его как раз из буста перенесли, вроде.

В любом случае эта оптимизация в моем случае ничего не даст, пока оставлю так. Ибо функция эта вызывается ооочень редка у меня, как раз когда пользователь мозгой еще шевелит и думает куда и на что далее ему тыкать :)

deterok ★★★★★
() автор топика
Последнее исправление: deterok (всего исправлений: 1)
Ответ на: комментарий от pon4ik

Спасибо. Если честно до до этого никогда таким в C++ не занимался. В Python и golang интроспекция решает!

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Если интересно, почитай Вандервуда и Джосатиса - «Шаблоны C++ справочник разработчика».

Там не про новый стандарт конечно, но много интересных плюшек есть.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Ну да, он как раз и должен был помочь. Тогда в move емантике я не вижу здесь смысла. Или он есть?

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Товарисч выше, не предлагал решение с мув семантикой - он просто предложил явно убрать оверехед от копирования, путём передачи аргумента по ссылке, либо мы про разный коммент.

И да, move doesn't move :)

pon4ik ★★★★★
()
Ответ на: комментарий от deterok

Да не, не небо и земля, 90% техник метапрограммирования основанны на предыдущем стандарте:) По новому - х3, самому было бы интересно.

pon4ik ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.