Здравствуйте, Аноним, Вы писали:
А>тупой вопрос, наверное, но вот не знаю как лучше сделать.
Вопрос не тупой, а криво сформулированный.
Перевожу на понятный язык.
Есть функция calculate над скалярными данными.
Хочется обобщить её, чтобы она работала не только со скалярами, но и с векторами (некоей известной размерности).
Встречные вопросы, для полноты картины:
Размерность векторов известна заранее?
— на стадии компиляции (функция параметризована типом: скаляр, K-мерный вектор, N-мерный вектор, и т.д.)
— на стадии вычисления (функция параметризована типом: скаляр либо вектор; в случае вектора размерность берётся как аргумент функции)
Функция имеет дело с одной или разными размерностями одновременно?
Кроме скаляров и векторов что-нибудь ещё может встретиться? ну там, матрицы...
А пока ответы я не узнал, предложу такой простенький вариант
тупой вопрос, наверное, но вот не знаю как лучше сделать.
есть старый код, который переделываем, чтобы вместо скалярной величины можно было засунуть массив.
надо чтобы 0.0 перешел в массив нулей.
class arrayData
{
...
// from 0.0 to all 0.0
arrayData(const double null)
{
m_data.resize(m_size);
std::fill(m_data.begin(), m_data.end(), null);
}
...
}
// используем: 0.0 плавно переходит в массив нулей.
// template<typename typeData>
typeData calculate<typeData>::engine()
{
...
typeData result = condition ? f(x) : 0.0;
...
}
надо чтобы calculate для double работал.
в этом решение не нравится что все double легко переводятся в нулевой массив. можно ли как это обезопасить это решение.
К>Вопрос не тупой, а криво сформулированный.
К>Перевожу на понятный язык. К>Есть функция calculate над скалярными данными. К>Хочется обобщить её, чтобы она работала не только со скалярами, но и с векторами (некоей известной размерности).
да! абсолютно так!
К>Встречные вопросы, для полноты картины: К>Размерность векторов известна заранее? К>- на стадии компиляции (функция параметризована типом: скаляр, K-мерный вектор, N-мерный вектор, и т.д.) К>- на стадии вычисления (функция параметризована типом: скаляр либо вектор; в случае вектора размерность берётся как аргумент функции) К>Функция имеет дело с одной или разными размерностями одновременно? К>Кроме скаляров и векторов что-нибудь ещё может встретиться? ну там, матрицы...
вектор всегда имеет размерность 10 и он известен уже на этапе компиляции. саму функцию мы используем в одном месте, чтобы посчитать скаляр double, а в другом хотим использовать для вектора. теоретически могут быть и матрицы, но пока это совсем не нужно.
Здравствуйте, avalanche2010, Вы писали:
A>вектор всегда имеет размерность 10 и он известен уже на этапе компиляции. саму функцию мы используем в одном месте, чтобы посчитать скаляр double, а в другом хотим использовать для вектора. теоретически могут быть и матрицы, но пока это совсем не нужно.
Я так понимаю, арифметика над векторами — покомпонентная. Тогда можно взглянуть в сторону std::valarray. Над ним уже определены всякие операции.
Дальнейшие пути:
1) Использовать только valarray<double> двух размерностей — 1 и 10. Параметризовать (хоть в шаблоне, хоть в рантайме) функцию этой размерностью.
2) Параметризовать функцию типом double / valarray<double> и словарём примитивов (нулевое значение 0.0 / valarray<double>(10), единичное значение 1 / valarray<double>(1.0,10), и т.д.)
3) Написать собственный класс, унаследованный от valarray, который конструирует себя с правильной размерностью. Но, боюсь, писанины и несовместимостей здесь будет очень много.
Очевидно, не устроит — если в роли typeData выступает вектор произвольной размерности std::vector или std::valarray.
Размерность нужно каким-то способом пригвоздить.
Например, сделать класс, оборачивающий (наследующийся от) стандартного вектора. Пусть он в своём дефолтном или скалярном конструкторе должным образом создаёт вектор.
Здравствуйте, Кодт, Вы писали:
К>Очевидно, не устроит — если в роли typeData выступает вектор произвольной размерности std::vector или std::valarray. К>Размерность нужно каким-то способом пригвоздить. К>Например, сделать класс, оборачивающий (наследующийся от) стандартного вектора. Пусть он в своём дефолтном или скалярном конструкторе должным образом создаёт вектор.
Так а вариант с traits(dims) не лучше, получается dims надо параметром передавать. Лучше уж обернуться.
Ну если уж на то пошло, так для контейнеров лучше бы и функцию переписать с передачей параметра по ссылке.
Здравствуйте, sokel, Вы писали:
S>Здравствуйте, Кодт, Вы писали:
К>>Очевидно, не устроит — если в роли typeData выступает вектор произвольной размерности std::vector или std::valarray. К>>Размерность нужно каким-то способом пригвоздить. К>>Например, сделать класс, оборачивающий (наследующийся от) стандартного вектора. Пусть он в своём дефолтном или скалярном конструкторе должным образом создаёт вектор.
S>Так а вариант с traits(dims) не лучше, получается dims надо параметром передавать. Лучше уж обернуться. S>Ну если уж на то пошло, так для контейнеров лучше бы и функцию переписать с передачей параметра по ссылке.
Вообще что то я торможу, изначально вариант с конструктором как раз и описан
Здравствуйте, sokel, Вы писали:
S>Так а вариант с traits(dims) не лучше, получается dims надо параметром передавать. Лучше уж обернуться.
"Лучше" зависит от того, как эта функция используется.
Если в системе есть ровно два типа данных — скаляр и десятимерный вектор, то конечно, удобно ввести класс "десятимерный вектор" (или N-мерный, где N — параметр шаблона). Шаблон функции параметризуется этим типом, и всё.
Если же предполагается, что выбор размерности происходит в рантайме (или этих размерностей просто слишком много, чтобы плодить инстансы классов и функций) — то можно сделать нешаблонную функцию, аргумент которой — размерность вектора.