I wrote a matrix template which is based on a std::vector. I am facing a problem when I want to proceed to an mathematical operation between two matrices: one which is a const reference and the other one which is not const and not a reference.
I am passing through a proxy to retrieve data stored in the std::vector:
template<typename T>
class Mat
{
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef typename std::vector<T>::size_type size_type;
private:
class Proxy
{
public:
Proxy(Mat& o, value_type i) : o(o), i(i)
{}
operator value_type()
{ return o.m[i]; }
reference operator=(const_reference other)
{ return o.m[i] = other; }
reference operator+=(const_reference other)
{ return o.m[i] += other; }
value_type operator*(const_reference other)
{ return o.m[i] * other; }
private:
Mat& o;
size_type i;
};
// Matrix methods and operator overloads.
Proxy operator[](size_type i)
{ return Proxy(*this, i); }
const Proxy operator[](size_type i) const
{ return Proxy(*this, i); }
Here is a sample from an extract of a test class which triggered an error:
void Test::buildMemoryMatrix(const Mat<int>& state)
{
Mat<int> t = state.getTransposed();
for(Mat<int>::size_type i = 0; i < state.rows(); ++i)
{
for(Mat<int>::size_type j = 0; j < t.cols(); ++j)
{
for(Mat<int>::size_type k = 0; k < state.cols(); ++k)
{
if(i == j)
{ continue; }
memory[i * memory.cols() + j] += state[i * state.cols() + k] * t[k * t.cols() + j];
}
}
}
}
Some precisions about the Mat<int> methods and Test class members:
The memory is a member of Test. It is represented as a Mat<int> object;
Mat::getTransposed() returns a transposed of a matrix;
Mat::rows() returns the number of rows of a matrix;
Mat::cols() returns the number of columns of a matrix
The following line give me some trouble:
memory[i * memory.cols() + j] += state[i * state.cols() + k] * t[k * t.cols() + j];
passing ‘const Mat::Proxy’ as ‘this’ argument discards qualifiers
[-fpermissive]
How to solve this problem?
Thanks for your answers.
Related
I need to overload the + operation like this a + b = max(a,b).
And accordingly I need it to work for matrix addition and matrix multiplication and some other operations (trace, power,etc.). Here \bigoplus is max operation
What's the best way to do this with Eigen? I read about eigen extension here, but I don't understand how to do that for my task.
Currently I have this:
#include <iostream>
#include <Eigen/Dense>
#include <algorithm>
using namespace Eigen;
namespace MaxAlgebra {
template <typename T>
T operator+(const T& a,const T& b) {
T c(a.rows(),a.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < a.cols(); ++j) {
c(i,j) = std::max(a(i,j),b(i,j));
}
}
return c;
}
template <typename T>
T operator*(const T& a,const T& b){
T c(a.rows(),b.cols());
for (uint i = 0; i < a.rows(); ++i) {
for (uint j = 0; j < b.cols(); ++j) {
std::vector<uint> values;
for (uint k = 0; k < a.cols(); ++k) {
values.push_back(a(i,k) * b(k,j));
}
c(i,j) = *std::max_element(begin(values),end(values));
}
}
return c;
}
template <typename T>
uint trace(const T& a) {
std::vector<uint> values;
for (uint i = 0; i < a.rows(); ++i) {
values.push_back(a(i,i));
}
return *std::max_element(begin(values),end(values));
}
}
int main() {
MatrixXd x(2,2);
MatrixXd y(2,2);
x(0,0) = 3;
x(1,0) = 2;
x(0,1) = 1;
x(1,1) = 2;
y(0,0) = 2;
y(1,0) = 1;
y(0,1) = 2;
y(1,1) = 3;
MatrixXd c = MaxAlgebra::operator*(x,y);
std::cout << "Here is the matrix a:\n" << x << std::endl;
std::cout << "Here is the matrix b:\n" << y << std::endl;
std::cout << "Here is the matrix c:\n" << c << std::endl;
return 0;
}
If I understand your algebra correctly, you could simply create a custom scalar type. This seems to work:
template<class T>
struct MaxAlg
{
T scalar;
MaxAlg() = default;
MaxAlg(T scalar) noexcept // implicit conversion for convenience
: scalar(scalar)
{}
explicit operator T() const noexcept
{ return scalar; }
MaxAlg& operator+=(MaxAlg o) noexcept
{
scalar = std::max(scalar, o.scalar);
return *this;
}
friend MaxAlg operator+(MaxAlg left, MaxAlg right) noexcept
{ left += right; return left; }
MaxAlg& operator*=(MaxAlg o) noexcept
{
scalar *= o.scalar;
return *this;
}
friend MaxAlg operator*(MaxAlg left, MaxAlg right) noexcept
{ left *= right; return left; }
friend bool operator==(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar == right.scalar; }
friend bool operator!=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar != right.scalar; }
friend bool operator<(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar < right.scalar; }
friend bool operator<=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar <= right.scalar; }
friend bool operator>(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar > right.scalar; }
friend bool operator>=(MaxAlg left, MaxAlg right) noexcept
{ return left.scalar >= right.scalar; }
friend std::ostream& operator<<(std::ostream& left, MaxAlg right)
{ return left << right.scalar; }
};
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgMatrix = Eigen::Matrix<MaxAlg<T>, Rows, Cols>;
template<class T, Eigen::Index Rows, Eigen::Index Cols>
using MaxAlgArray = Eigen::Array<MaxAlg<T>, Rows, Cols>;
using MaxAlgMatrixXd = MaxAlgMatrix<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgVectorXd = MaxAlgMatrix<double, Eigen::Dynamic, 1>;
using MaxAlgArrayXXd = MaxAlgArray<double, Eigen::Dynamic, Eigen::Dynamic>;
using MaxAlgArrayXd = MaxAlgArray<double, Eigen::Dynamic, 1>;
int main()
{
Eigen::MatrixXd a = Eigen::MatrixXd::Random(10, 10);
Eigen::MatrixXd b = Eigen::MatrixXd::Random(10, 10);
MaxAlgMatrixXd maxalg_a = a.cast<MaxAlg<double> >();
MaxAlgMatrixXd maxalg_b = b.cast<MaxAlg<double> >();
std::cout << (maxalg_a * maxalg_b).cast<double>() << "\n\n";
std::cout << (maxalg_a.array() + maxalg_b.array()).cast<double>() << "\n\n";
std::cout << a.cwiseMax(b) << "\n\n";
}
This disables Eigen's vectorization but the compiler can still do it when you compile with -O3 and it is a lot less work.
I want to create a generalized heap data structure, and facing an issue with passing template comparator.
template<typename T, typename C = less<T> > class Heap{
vector<T> *heap;
public:
Heap(vector<T> *arr){
heap = new vector<T> (arr->begin(), arr->end());
build_heap();
}
void build_heap(){
size_t n = heap->size();
for (size_t i=(n-1)/2; i>=0; i--){
shiftDown(i);
}
}
void shiftDown(size_t i){ /// heap logic
while(i < heap->size()){
size_t child = 2*i+1;
// int min_ind = 2*i+1;
if(child >= heap->size())
return;
if(child+1 < heap->size()){
if( C(heap->at(child+1),heap->at(child)) ){ // <----- using C as comparator
child++;
}
}
if( C(heap->at(child), heap->at(i)) ){ // <----- using C as comparator
swap(heap->at(child), heap->at(i));
i = child;
}
else
break;
}
}
};
int main(){
vector<int> v={8,7,6,5,4,3,2,1};
Heap<int, less<int> > heap(&v);
}
error
heap.cpp: In instantiation of ‘void Heap<T, C>::shiftDown(size_t) [with T = int; C = std::less<int>; size_t = long unsigned int]’:
heap.cpp:15:4: required from ‘void Heap<T, C>::build_heap() [with T = int; C = std::less<int>]’
heap.cpp:10:3: required from ‘Heap<T, C>::Heap(std::vector<_Tp>*) [with T = int; C = std::less<int>]’
heap.cpp:49:34: required from here
heap.cpp:32:9: error: no matching function for call to ‘std::less<int>::less(__gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&, __gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&)’
32 | if( C(heap->at(child+1),heap->at(child)) ){
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
detailed error
i'm following same syntex of declaration as stl c++ do, still i'm getting error. please help me out.
template<typename T, typename C = less<T> > class Heap;
any help or pointer to help is appreciated. thank you.
template<class T>
class Comparator{
bool operator()(const T &a, const T &b){
...
// returns logic
}
}
template<class T, class Comp >
class AnyClass{
public:
...
void function(){
// code ...
Comp<T>()(obj1, obj2);
}
...
}
calling sytex :
...
AnyClass *obj = new AnyClass<Type , Comparator>();
obj.function()
...
passing Comparator to templated class and when we need to compare objects
we create a functional object and call operator() with args to compare.
In question, that object is less<int>.
Comp<T>()(obj1, obj2);
I am trying to implement a vector using my own class so I can not do the initialiser list part
# include <iostream>
# include <exception>
# include<initializer_list>
template <class T>
class vector {
public:
T* a;
T n;
int pos, c;
vector() { a = 0; n = 0; }
vector(T n) : n(n) { a = new T[n]; }
vector(std::initializer_list <vector> l) {
a = new T[int(sizeof(l))];
for (int f : l)
*(a + f) = l.begin() + f;
}
void push_back(T k) {
int i = k;
*(a + n) = k;
}
vector& operator= (vector&& th) {
this->a = th.a;
th.a = nullptr; return (*this);
}
vector& operator=(vector& k)
{
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
I am just trying to use pointer offset notation to take the initializer list items into the dynamic array but I get errors VS 17 IDE
Severity Code Description Project File Line Suppression
Error C2440 '=': cannot convert from 'const _Elem *' to 'T'
Error C2440 'initializing': cannot convert from 'const _Elem' to 'int'
Hello Nimrod!
#include <iostream>
#include <exception>
#include <initializer_list>
// normally people don't place a space between '#' and 'include'
template <class T>
class vector {
public:
T* a;
int n;
// probably it is length the vector
// change T to int
int pos, c;
vector() {
a = nullptr;
// do not use '0' to instruct null pointer
n = 0;
}
vector(int n): n(n) { a = new T[n]; }
vector(std::initializer_list<T> l) {
a = new T[l.size()];
// redundant force cast from size_t to int
for (int i = 0; i < l.size(); i++) {
a[i] = l.begin()[i];
}
// for (int f : l) # it seems that you wrote JavaScript before?
// *(a + f) = l.begin() + f;
}
void push_back(T k) {
// assigns "T k" to "int i"? it's confusing
// int i = k;
// *(a + n) = k;
}
// probably still many problems
vector& operator=(vector&& th) {
this->a = th.a;
th.a = nullptr;
return (*this);
}
vector& operator=(vector& k) {
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
You still need more practice. XP
In your context of code, template variable for initializer_list should be T rather than int.
Range for loop with initializer_list<T> will fetch the values
in the list. Therefore it should belong to T.
Good morning everyone.
I am new to C++ 11 multithreading theme and trying to write down a code that add two vectors of equal sizes in asynchronous way.
This means, if I have two vectors:
vector<int> fisrt = {1, 2, 3};
vector<int> second = {3, 2, 1};
first += second; // first = {4, 4, 4}
I wrote Paginator class which splits vector on "pages" with appropriate page_size.
My idea of vectors addition in asynchronous way is next: split vectors on pages with choosen page_size, and add pages of first and second vectors in asynchronous way.
Paginator class implementation
template<class Iter>
class IterRange {
public:
explicit IterRange(Iter first, Iter last) : first_(first), last_(last) {}
Iter begin() { return first_; }
const Iter begin() const { return first_; }
Iter end() { return last_; }
const Iter end() const { return last_; }
private:
Iter first_;
Iter last_;
};
template<class Iter>
IterRange<Iter> MakeIterRange(Iter first, Iter last) {
return IterRange<Iter> {first, last };
}
template<class Iter>
class Paginator {
public:
Paginator(Iter first, Iter last, size_t page_size) : page_size_(page_size) {
size_t pages_count = static_cast<size_t> (floor((double)distance(first, last) / page_size_));
pages_.reserve(pages_count);
size_t page_id = 0u;
Iter begin_page = first;
for (page_id, begin_page; page_id < pages_count; ++page_id, begin_page += page_size_) {
pages_.push_back(MakeIterRange( begin_page, begin_page + page_size ));
}
// If some elements less than page_size_ is left
if (begin_page != last) {
pages_.push_back(MakeIterRange(begin_page, begin_page + distance(begin_page, last)));
}
}
auto begin() { return pages_.begin(); }
auto begin() const { return pages_.begin(); }
auto end() { return pages_.end(); }
auto end() const { return pages_.end(); }
private:
size_t page_size_;
vector<IterRange<Iter>> pages_;
};
template<class Iter>
Paginator<Iter> MakePaginator(Iter first, Iter last, size_t page_size) {
return{ first, last, page_size };
}
template<class Container> // And the same for non constant Container
auto Paginate(const Container & c, size_t page_size) {
return MakePaginator(begin(c), end(c), page_size);
}
This Paginate procedure is used in operator+= in my Matrix class.
Matrix class fields are:
Matrix sizes along Ox and Oy direction respectively: size_t nx_, size_t ny_.
Vector of (nx_ * ny_) size, which stores all elements in matrix: vector body_.
Operator += for Matrix
template
inline Matrix & Matrix::operator+=(const Matrix & other) {
size_t threads_numb = thread::hardware_concurrency();
size_t page_size = static_cast<size_t> (ceil((double)body_.size() / threads_numb));
vector<future<void>> futures;
auto page_1 = page::Paginate(body_, page_size);
auto page_2 = page::Paginate(other.body_, page_size);
auto it_2 = page_2.begin();
for (auto it = page_1.begin(); it != page_1.end(); ++it, ++it_2) {
futures.push_back(
async([it, it_2] { transform(it->begin(), it->end(), it_2->begin(), it->begin(), plus<T>()); })
);
}
return *this;
}
But as a result I get iterator out of range error! How could I fix this?
P.S. Sorry for bad representation of first string in operator +=. Could not fix this problem :(
In this game of life program the user tells the solve function how to access required data. Is it possible to be const-correct inside the function without supplying it with both const and non-const versions of data accessors? Clang complains about the constness of neighbor cell data when checking whether neighbors are alive or not (candidate function not viable: 1st argument ('const Cell') would lose const qualifier):
#include "array"
#include "iostream"
using namespace std;
struct Cell {
bool is_alive = false; int nr_live_neighs = 0;
};
template<
class Grid,
class Is_Alive_Getter,
class Nr_Live_Neighs_Getter
> void solve(
Grid& grid,
Is_Alive_Getter Is_Alive,
Nr_Live_Neighs_Getter Nr_Live_Neighs
) {
for (size_t i = 1; i < grid.size() - 1; i++) {
auto& cell = grid[i];
const auto // how to stay const-correct here?
&neigh_neg = grid[i - 1],
&neigh_pos = grid[i + 1];
if (Is_Alive(neigh_neg)) Nr_Live_Neighs(cell)++;
if (Is_Alive(neigh_pos)) Nr_Live_Neighs(cell)++;
}
for (auto& cell: grid) {
if (Nr_Live_Neighs(cell) == 3)
Is_Alive(cell) = true;
else if (Nr_Live_Neighs(cell) != 2)
Is_Alive(cell) = false;
Nr_Live_Neighs(cell) = 0;
}
}
int main() {
std::array<Cell, 10> grid;
for (size_t i = 0; i < grid.size(); i++) {
grid[i].is_alive = (i % 4 > 0);
}
solve(
grid,
[](Cell& cell_data) -> bool& {
return cell_data.is_alive;
},
[](Cell& cell_data) -> int& {
return cell_data.nr_live_neighs;
}
);
return 0;
}
I can use
if (Is_Alive(const_cast<decltype(cell)>(neigh_neg)))
instead of
if (Is_Alive(neigh_neg))
inside the solver but that feels hacky even though it doesn't seem to affect time to solution. What if a non-const reference isn't available to use in decltype? Is there a generic way to cast away the const by only referring to the const variable?