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


Автор: kosmonaFFFt 31.7.2012, 16:34
Доброго времени суток...

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

имеется:
Код

using ::std::vector;
using ::std::function;
using ::boost::numeric::ublas::matrix;

typedef double decimal_t;
typedef vector<decimal_t> vector_t;
typedef function<decimal_t(const vector_t&) > multivariate_function_t;
typedef matrix<decimal_t> matrix_t;

...

matrix_t _pts;
vector_t _I;

void _eval_fn_values(const multivariate_function_t& fn)
{
    for (auto row = 0; row < _pts.size1(); ++row)
    {
        matrix_row<matrix_t> point(_pts, row);
        vector_t x(point.begin(), point.end()); // TODO: Try to rewrite this without matrix row copy.
        _I[row] = fn(x);
    }
}


Соотвественно вопрос - можно ли как-нибудь переопределить тип multivariate_function_t, или сделать еще что-нибудь, чтобы избежать копирования данных из строки матрицы в вектор?

Заранее спасибо...

Автор: boostcoder 31.7.2012, 16:54
почему бы в твою multivariate_function_t не передать ссылку на твой matrix_row ?

Добавлено через 6 минут и 13 секунд
кто такой matrix_row ?

Автор: kosmonaFFFt 31.7.2012, 17:06
Цитата(boostcoder @  31.7.2012,  20:54 Найти цитируемый пост)
кто такой matrix_row ? 

Он из boost::numeric::ublas - шаблон, позволяющий получить доступ к строке матрицы.


Цитата(boostcoder @  31.7.2012,  20:54 Найти цитируемый пост)
почему бы в твою multivariate_function_t не передать ссылку на твой matrix_row ?

Потому что уже есть функции, принимающие ссылку на std::vector и работающие с ним.

Чтобы был понятнее зачем это надо - в данный момент реализую алгоритм глобальной оптимизации, соответственно оптимизатор должен принимать на входе функцию, которую оптимизирует...

Автор: boostcoder 31.7.2012, 17:08
Цитата(kosmonaFFFt @  31.7.2012,  17:06 Найти цитируемый пост)
Потому что уже есть функции, принимающие ссылку на std::vector и работающие с ним.

ну так ты сейчас лечишь последствия.
меняй реализацию так, чтоб multivariate_function_t принимала ссылку на matrix_row.
или что?

Автор: kosmonaFFFt 31.7.2012, 17:13
В идеале хотелось бы, чтобы функция принимала некий обобщенный вектор, который был бы совместим и с std::vector и с matrix_row... Может в boost есть какой-нибудь враппер для stl-совместимых коллекций и можно было бы использовать его?

Автор: boostcoder 31.7.2012, 17:14
Цитата(kosmonaFFFt @  31.7.2012,  16:34 Найти цитируемый пост)
можно ли как-нибудь переопределить тип multivariate_function_t, или сделать еще что-нибудь, чтобы избежать копирования данных из строки матрицы в вектор?

ох и слеп я, слеп %)

да, ты можешь переопределить тип multivariate_function_t при помощи http://www.boost.org/doc/libs/1_50_0/libs/functional/overloaded_function/doc/html/index.html, и тогда multivariate_function_t сможет вызывать перегруженные функции принимающие вектор и matrix_row.

я все правильно понял?

Добавлено @ 17:18
т.е. в итоге получится что-то типа:
Код

typedef boost::overloaded_function<
      decimal_t(const vector_t&)
    , decimal_t(const matrix_row&)
> multivariate_function_t;

..

decimal_t func_for_vector(const vector_t& v) {}
decimal_t func_for_matrix_row(const matrix_row& m) {}

...

multivariate_function_t func(func_for_vector, func_for_matrix_row);

..

_eval_fn_values(func);


Добавлено @ 17:19
Цитата(kosmonaFFFt @  31.7.2012,  17:13 Найти цитируемый пост)
хотелось бы, чтобы функция принимала некий обобщенный вектор, который был бы совместим и с std::vector и с matrix_row.

это вряд ли...
не могу найти доку по matrix_row. дай плиз ссылку ;)

Автор: kosmonaFFFt 31.7.2012, 17:27
Кажется я уже ближе к решению проблемы, только вот остается проблема работы оптимизатора со старыми функциями, принимающими вектор... Хотелось бы иметь некий абстрактный враппер для stl-совместимых коллекций, но видимо о многом мечтаю...

На крайний случай можно использовать vector<vector<double>> вместо матрицы... )

Автор: boostcoder 31.7.2012, 17:32
kosmonaFFFt, повторюсь: ты лечишь последствия. последствия кривого дизайна.
но решать тебе, конечно.

Автор: kosmonaFFFt 31.7.2012, 17:42
После Java довольно трудно делать хороший дизайн на C++... Пока еще не очень поздно, хотелось бы данный пункт дизайна вылечить как-нибудь...
boostcoder, интересно твое мнение следующего решения:
переопределить vector_t так, чтобы он мог без сильных накладных расходов враппить (например с помощью специализации шаблона и неявного приведения типов) другие коллекции, предоставляя к ним единый интерфейс...

Автор: boostcoder 31.7.2012, 18:19
Цитата(kosmonaFFFt @  31.7.2012,  17:42 Найти цитируемый пост)
переопределить vector_t

а может проще функцию _eval_fn_values сделать шаблонной принимающей произвольный тип? тогда ее можно будет специализировать по множеству критериев.

Автор: kosmonaFFFt 31.7.2012, 18:58
Немного не то... Идет оптимизация функции, принимающей вектор, а _eval_fn_values ее просто вызывает внутри себя... Вот если бы оптимизируемая функция могла принимать какую-то одну обобщенную обертку вида vector_wrapper<double>, для которой, при необходимости, можно было бы написать специализации для разных коллекций, это было бы то... Тогда бы все функции принимали эту обертку, а при компиляции подсовывалась бы нужная специализация... Такое вообще возможно?

Автор: boostcoder 31.7.2012, 19:03
Цитата(kosmonaFFFt @  31.7.2012,  18:58 Найти цитируемый пост)
если бы оптимизируемая функция могла принимать какую-то одну обобщенную обертку вида vector_wrapper<double>, для которой, при необходимости, можно было бы написать специализации для разных коллекций, это было бы то...

это возможно.

Цитата(kosmonaFFFt @  31.7.2012,  18:58 Найти цитируемый пост)
а при компиляции подсовывалась бы нужная специализация

а в чем тут разница между "функция могла принимать какую-то одну обобщенную обертку", и "при компиляции подсовывалась бы нужная специализация" ?
С++ - компилируемый ЯП.

я все же наверное не очень понимаю задачу... попробуй на пальцах ;)

Автор: kosmonaFFFt 31.7.2012, 19:08
Хотелось бы как-то так (нерабочий пример):
Код

template<typename T, typename C>
class container_wrapper
{
};

template<typename T>
class container_wrapper<T, vector<T> >
{
};

template<typename T>
class container_wrapper<T, list<T> >
{
};

void fn(const container_wrapper<int>& w)
{
    
}

int main(...)
{
    vector<int> v;
    fn(v);
}


и чтобы при этом можно было бы неявно преобразовывать vector<int> в collection_wrapper<int, vector<int> >.

Автор: boostcoder 31.7.2012, 19:09
Цитата(kosmonaFFFt @  31.7.2012,  18:58 Найти цитируемый пост)
vector_wrapper<double>

мы можем специализировать как для хранимого типа, так и для некоторых условий и констант, обязав себя соблюсти интерфейс.
к примеру:
Код

enum iface_strategy {
    iface_vector
   ,iface_matrix
   ,iface_2d_vector
   ,iface_3d_vector
};

template<typename T, iface_strategy>
struct vector_wrapper;

template<typename T>
struct vector_wrapper<T, iface_vector> {
    typedef typename std::vector<T>::iterator iterator;
    typedef typename std::vector<T>::const_iterator const_iterator;

   iterator begin() {...}
   const_iterator begin() {...}
   iterator end() {...}
   const_iterator end() {...}
};
template<typename T>
struct vector_wrapper<T, iface_matrix> {
    typedef typename boost::matrix<T>::iterator iterator;
    typedef typename boost::matrix<T>::const_iterator const_iterator;

   iterator begin() {...}
   const_iterator begin() {...}
   iterator end() {...}
   const_iterator end() {...}
};

Автор: kosmonaFFFt 31.7.2012, 19:21
А можно ли добиться, чтобы передаваемый в функцию враппер параметризовался только одним аргументом - типом хранящегося в коллекции значения?

Автор: boostcoder 31.7.2012, 19:24
Цитата(kosmonaFFFt @  31.7.2012,  19:08 Найти цитируемый пост)
Хотелось бы как-то так (нерабочий пример):

так-то можно. но я все равно не понимаю, зачем..

Автор: kosmonaFFFt 31.7.2012, 19:32
Чтобы было:
Код

typedef function<double(const vector_wrapper<double>& v)> fn_t;

class optimizer1 {
    void optimize(const fn_t& fn, other_params params);
}

class optimizer2 {
    void optimize(const fn_t& fn, other_params params);
}

...

void optimizer1::optimize(const fn_t& fn, other_params params) {
    some_vector_like_container c;
    fn(c);
}

double fn_1(const vector_wrapper<double>& v) {
}

...

vector<double> v;
fn_1(v);

...

optimizer1 o;
o.optimize(fn, ...);

Автор: boostcoder 31.7.2012, 19:41
Цитата(kosmonaFFFt @  31.7.2012,  19:21 Найти цитируемый пост)
А можно ли добиться, чтобы передаваемый в функцию враппер параметризовался только одним аргументом - типом хранящегося в коллекции значения?

да. но а как тогда специализировать контейнер который представляет враппер?

Автор: kosmonaFFFt 31.7.2012, 19:44
Цитата(boostcoder @  31.7.2012,  23:41 Найти цитируемый пост)
да. но а как тогда специализировать контейнер который представляет враппер?

А компилятор не может этого сделать по типу передаваемого аргумента? Т. е. если передаем аргумент типа vector<int>, то он кастуется в wrapper<int, vector<int>>...

Автор: boostcoder 31.7.2012, 19:51
Цитата(kosmonaFFFt @  31.7.2012,  19:21 Найти цитируемый пост)
типом хранящегося в коллекции значения? 

 - я понял в прямом смысле. т.е. double, float, long...
а ты про специализированный контейнер?
типа?:
Код

template<typename C>
struct vector_wrapper<vector<double>> {};
template<typename C>
struct vector_wrapper<matrix<double>> {};

?

Автор: kosmonaFFFt 31.7.2012, 19:58
Ага, так тоже пойдет, вроде у всех контейнеров, что я видел, есть внутри что-то наподобие
Код

typedef typename T value_type;

и его можно использовать в враппере...

Автор: boostcoder 31.7.2012, 20:23
так вопрос решен?

Автор: kosmonaFFFt 31.7.2012, 20:26
Теоретически... ) Как решу практически, закрою тему...
Спасибо за помощь...

З.Ы. В общем немного разобрался с параметризацией шаблонов, проблему решил, хоть и немного по другому...

Автор: kosmonaFFFt 10.9.2012, 18:19
Ап...

Посмотрел вот тут на std::function, и подумал, а нельзя ли сделать подобный враппер для объектов, имеющих оператор [], чтобы можно было бы написать что-то подобное следующему:
Код

void superFunction(const ArrayWrapper<int>& w)
{
...
}

std::vector<int> v1;
int* v2 = new int[...];
SomeOtherIntVector v3;

superFunction(v1);
superFunction(v2);
superFunction(v3);

Попытался разобраться в исходниках std::function, но суть так и не понял, как именно там реализовали то, что можно создать объект std::function из всего, что имеет operator(), соответствующей сигнатуры...

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