我想编写一个c ++矩阵操作代码,某些函数的某些操作是相同的。我想知道是否有一些方法可以合并它们?例如:
void add1(vector<vector<double> > &m){
for(int i = 0; i < m.size(); ++i){
for(int j = 0; j < m[i].size(); ++j){
m[i][j] += 1.0;
}
}
}
void minus1(vector<vector<double> > &m){
for(int i = 0; i < m.size(); ++i){
for(int j = 0; j < m[i].size(); ++j){
m[i][j] -= 1.0;
}
}
}
两段代码几乎相同。如何避免重写两次?是否有类似模板可以自动生成代码?
答案 0 :(得分:10)
您可以定义一个函数模板,并将迭代的核心逻辑放在该函数中的元素上。
模板参数可以是functor,可用于定义每个特定调用的内容。
// Change m to be a reference so the modifications to the elements
// are visible in the calling function.
template <typename Functor>
void for_each_member(vector<vector<double> >& m, Functor functor)
{
for(std::size_t i = 0; i < m.size(); ++i){
for(std::size_t j = 0; j < m[i].size(); ++j){
functor(m[i][j]);
}
}
}
void add1(vector<vector<double> >& m){
for_each_member(m, [](double& item) { item += 1.0;});
}
void minus1(vector<vector<double> >& m){
for_each_member(m, [](double& item) { item -= 1.0;});
}
答案 1 :(得分:3)
您可以通过以下方式进行概括:
template<typename T, typename F>
void for_each_element(std::vector<std::vector<T>> &m, F &&f) {
std::for_each(m.begin(), m.end(), [f] (auto &&v) {
std::transform(v.begin(), v.end(), v.begin(), f);
});
}
但是请注意,将矩阵表示为std::vector<std::vector<T>>
并不是非常缓存,因为您在整个内存中分析矩阵的行。如果你有一个自定义矩阵类在内部使用一个std::vector
并且会重载row/column major访问的下标运算符会更好。
答案 2 :(得分:1)
您可以使用第二个参数创建一个func,然后将其添加到矩阵的每个成员。
答案 3 :(得分:0)
你可以这样定义
template <template <class> class pred>
void apply(vector<vector<double>> & m) {
for (auto & i : m)
for (auto & j : i)
j = pred<double>()(j, 1.0);
}
如需添加,请致电
apply<std::plus>(m);
类似地,对于减法
apply<std::minus>(m);
您还可以使用<functional>
查看有效的DEMO。
答案 4 :(得分:0)
您也可以为矩阵编写迭代器。这不完整但会给你一个想法:
#include <vector>
#include <algorithm>
template< class _T >
class Matrix
{
public:
std::vector< std::vector< _T > > m_matrix;
void alloc( size_t rows, size_t cols )
{
m_matrix.resize( rows );
std::for_each( m_matrix.begin(), m_matrix.end(), [cols](std::vector<_T> &t){t.resize(cols);});
}
class iterator
{
public:
iterator( std::vector< std::vector< _T > > & v ):
m_vbegin( v.begin() ),
m_vi( v.begin() ),
m_i( m_vi->begin() ),
m_vend( v.end() )
{}
iterator& operator++()
{
if ( ++m_i == m_vi->end() )
{
if ( ++m_vi != m_vend )
m_i = m_vi->begin();
}
return (*this);
}
void gotobegin()
{
m_vi=m_vbegin;
m_i=m_vi->begin();
}
void gotoend()
{
m_vi=m_vend;
}
_T & operator*()
{
return *m_i;
}
bool operator==(const iterator & rhs )
{
if ( m_vi==rhs.m_vi && (m_vi==m_vend || m_i==rhs.m_i) )
return true;
return false;
}
bool operator!=(const iterator & rhs )
{
return !( *this == rhs );
}
private:
typename std::vector< std::vector< _T > >::iterator m_vi;
const typename std::vector< std::vector< _T > >::iterator m_vbegin;
const typename std::vector< std::vector< _T > >::iterator m_vend;
typename std::vector< _T >::iterator m_i;
};
iterator begin(){ return iterator(m_matrix); }
iterator end(){ iterator ret(m_matrix); ret.gotoend(); return ret;}
};
int main( void )
{
Matrix<double> matrix;
matrix.alloc( 4000, 4000 );
std::for_each( matrix.begin(), matrix.end(), []( double &t){ t=1.0;} );
std::for_each( matrix.begin(), matrix.end(), []( double &t){ t+=1.0;} );
return 0;
}
答案 5 :(得分:-1)
除了其他答案。您还可以使用std::function
(请参阅http://en.cppreference.com/w/cpp/utility/functional/function)。在这里,您必须定义返回类型以及参数类型。使用它,您可以传递任何可调用的内容。
以下是一个例子:
#include <iostream>
#include <functional>
#include <vector>
using matrix = std::vector<std::vector<double>>;
void for_each_member(matrix& m, std::function<void(double&)> functor)
{
for (auto &vec : m)
for (auto &element : vec)
functor(element);
}
static void sub(double &ele)
{
--ele;
}
int main()
{
matrix m = { {1,2}, {3,4} };
for_each_member(m, [](auto &ele) { ++ele; });
for_each_member(m, [](auto &ele) {std::cout << ele << " "; });
std::cout << "\n";
for_each_member(m, sub);
for_each_member(m, [](auto &ele) {std::cout << ele << " "; });
std::cout << "\n";
return 0;
}
答案 6 :(得分:-2)
这个怎么样:
#include "stdafx.h"
#include <vector>
using namespace std;
#define plus +=
#define minus -=
#define DO(x,m) for (size_t i = 0; i < m.size(); ++i) \
for (size_t j = 0; j < m[i].size(); ++j) \
m[i][j] x 1.0; \
int _tmain(int argc, _TCHAR* argv[])
{
vector<vector<double>> rows;
vector<double> col1(2, 3);
vector<double> col2(2, 3);
rows.push_back(col1);
rows.push_back(col2);
DO(plus,rows);
return 0;
}
答案 7 :(得分:-2)
免责声明:我打破了vector提供的一些C ++封装,以显示提供所需内容的潜在更快的解决方案。在SO上使用C ++标签的一些纯粹主义者肯定会因为向你展示一些 ahem C代码而敲门。但无论如何我还是要告诉你。你可以自己做出决定。
inline void add_to_every_element(vector<double>* rows, size_t m_size, double d)
{
for (size_t i = 0; i < m_size; i++)
{
size_t row_size = rows[i].size();
double* row = rows[i].data();
for (size_t j = 0; j < row_size; j++)
{
row[j] += d;
}
}
}
void add1(vector<vector<double> > &m)
{
add_to_every_element(m.data(), m.size(), 1.0);
}
void minus1(vector<vector<double>>& m)
{
add_to_every_element(m.data(), m.size(), -1.0);
}