I don't know this question is clear or not.
I want make a simple matrix like that
template<typename T>
class Matrix {
private:
T* m_buffer;
int m_row;
int m_col;
public:
template<int N, int M>
Matrix(const T (&x)[N][M]);
};
template<typename T>
template<int N, int M>
inline
Matrix<T>::Matrix(const T (&x)[N][M]) : m_row(N), m_col(M) {
m_buffer = new T[N*M];
std::copy(x, x + N*M, m_buffer);
}
int main() {
int a[2][3] = { {1, 2, 3},
{4, 5, 6} };
Matrix<int> x(a); // This not work
return 0;
}
It seem be not working and get some error when compile. I want to ask how to fix this error.
/usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = const int (*)[3]; _OI = int*]’:
/usr/include/c++/5/bits/stl_algobase.h:400:44: required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const int (*)[3]; _OI = int*]’
/usr/include/c++/5/bits/stl_algobase.h:436:45: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const int (*)[3]; _OI = int*]’
/usr/include/c++/5/bits/stl_algobase.h:469:8: required from ‘_OI std::copy(_II, _II, _OI) [with _II = const int (*)[3]; _OI = int*]’
../main.cpp:34:13: required from ‘Matrix<T>::Matrix(const T (&)[N][M]) [with int N = 2; int M = 3; T = int]’
subdir.mk:18: recipe for target 'main.o' failed
../main.cpp:40:21: required from here
/usr/include/c++/5/bits/stl_algobase.h:340:18: error: invalid conversion from ‘const int*’ to ‘int’ [-fpermissive]
*__result = *__first;
Thank you for your support.
The issue seems to be the call to std::copy. You are passing a reference as the first parameter to std::copy, which is not correct. You should be passing a pointer.
To pass a pointer, the following could be done:
std::copy(&x[0][0], &x[0][0] + N*M, m_buffer);
In the above, you are passing the address of the first element in the two dimensional array, and since the data in a 2D array is contiguous, the address of one past the last element is merely specifying N*M.
Live Example
It's not quite what you're asking but using non-type template arguments, you can achieve a constructor like
Matrix<T,ROWS,COLS>(const T(& initializer)[ROWS][COLS])
allows
Matrix<int,2,2> a({{2,2},
{2,2}});
which has the added bonus of allowing you to enforce multiplication rules with the compiler
Try something like this:
// TemplateMatrix.hpp
#pragma once
#include <cstdlib>
#include <cstring>
template<class T, int M, int N>
class Matrix
{
private:
T *m_buffer;
public:
Matrix(const T matrix[M][N])
{
m_buffer = new T[M*N];
memcpy(m_buffer, matrix, M*N*sizeof(T));
}
};
Then, in the main function
#include <iostream>
#include <cstdlib>
#include "TemplateMatrix.hpp"
using namespace std;
int main()
{
int a[2][2] = {{1,1}, {2,2}};
Matrix<int, 2, 2> m(a);
}
Related
I have a small working code for finding a range of items that uses a special compare method. But when I try to rewrite it with lower_bound() and upper_bound() function, I get a strange error. I have written a small code to show my problem. Here is the code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
int main() {
string str = "banana";
string keyword = "ana";
int sa_idx[] = {5, 3, 1, 0, 4, 2};
vector<int> sa(sa_idx, sa_idx + sizeof(sa_idx) / sizeof(int) );
auto cmp = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a, keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp) -
lower_bound(sa.begin(), sa.end(), keyword, cmp)) << endl;
return 0;
}
As you see, compare function uses keyword and value of sa array for compare decision. A standard says:
The type Type1 must be such that an object of type ForwardIt can be
dereferenced and then implicitly converted to Type1. The type Type2
must be such that an object of type T can be implicitly converted to
Type2.
My compare function has int type for first argument(because of vector<int> of array) and string for the second argument type(as type of keyword). But I don't know why I get following error:
In file included from /usr/include/c++/6/bits/stl_algobase.h:71:0,
from /usr/include/c++/6/bits/char_traits.h:39,
from /usr/include/c++/6/ios:40,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from prog.cpp:1:
/usr/include/c++/6/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Val_comp_iter<_Compare>::operator()(_Value&, _Iterator) [with _Value = const std::__cxx11::basic_string<char>; _Iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = main()::<lambda(const int&, const string&)>]’:
/usr/include/c++/6/bits/stl_algo.h:2049:14: required from ‘_ForwardIterator std::__upper_bound(_ForwardIterator, _ForwardIterator, const _Tp&, _Compare) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = __gnu_cxx::__ops::_Val_comp_iter<main()::<lambda(const int&, const string&)> >]’
/usr/include/c++/6/bits/stl_algo.h:2114:32: required from ‘_FIter std::upper_bound(_FIter, _FIter, const _Tp&, _Compare) [with _FIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Tp = std::__cxx11::basic_string<char>; _Compare = main()::<lambda(const int&, const string&)>]’
prog.cpp:19:57: required from here
/usr/include/c++/6/bits/predefined_ops.h:173:11: error: no match for call to ‘(main()::<lambda(const int&, const string&)>) (const std::__cxx11::basic_string<char>&, int&)’
{ return bool(_M_comp(__val, *__it)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cpp:14:61: note: candidate: main()::<lambda(const int&, const string&)>
auto cmp = [&str] (const int &a, const string &keyword) -> bool
^~~~
prog.cpp:14:61: note: no known conversion for argument 1 from ‘const std::__cxx11::basic_string<char>’ to ‘const int&’
Have I missed something super obvious? Because it seems compiler looks for string as first argument of compare function.
Your problem here is that std::uppper_bound requires the cmp be of the signature
bool(T, decltype(*Iterator))
std::lower_bound has the opposite requirement though and wants
bool(decltype(*Iterator), T)
so you can't use the same comparator with both functions. There are other ways to modify the code but just adding a second comparator like
auto cmp1 = [&str](const string &keyword, const int &a) -> bool
{
return strncmp(keyword.c_str(), str.c_str() + a, keyword.length()) < 0;
};
auto cmp2 = [&str] (const int &a, const string &keyword) -> bool
{
return strncmp(str.c_str() + a, keyword.c_str(), keyword.length()) < 0;
};
cout << (upper_bound(sa.begin(), sa.end(), keyword, cmp1) -
lower_bound(sa.begin(), sa.end(), keyword, cmp2)) << endl;
allows the code to compile.
#include <iostream>
#include <algorithm>
using namespace std;
struct arr
{
int a;int b;
}a[1000];
bool comp(arr &lhs, arr &rhs)
{ return lhs.a < rhs.a ; }
int main()
{
int n,i ;
sort(a,a+n,comp);
int ind= lower_bound(a,a+n,x,comp)-a;
return 0;
}
Error message :
/usr/include/c++/4.9/bits/predefined_ops.h: In instantiation of 'bool
__gnu_cxx::__ops::_Iter_comp_val<_Compare>::operator()(_Iterator, _Value&) [with _Iterator = arr*; _Value = const int; _Compare = bool ()(arr&, arr&)]': /usr/include/c++/4.9/bits/stl_algobase.h:965:30:
required from '_ForwardIterator std::__lower_bound(_ForwardIterator,
_ForwardIterator, const _Tp&, _Compare) [with _ForwardIterator = arr; _Tp = int; _Compare = __gnu_cxx::__ops::_Iter_comp_val]' /usr/include/c++/4.9/bits/stl_algo.h:2036:46: required from
'_FIter std::lower_bound(_FIter, _FIter, const _Tp&, _Compare) [with
_FIter = arr*; _Tp = int; _Compare = bool ()(arr&, arr&)]' prog.cpp:28:38: required from here
/usr/include/c++/4.9/bits/predefined_ops.h:141:37: error: invalid
initialization of reference of type 'arr&' from expression of type
'const int' { return bool(_M_comp(__it, __val)); }
^
I wish to use lower_bound over the struct to search for the value x that equals to a[i].a ? I have constructed the comparator function accordingly but getting a long error message of which I am not able to make anything.
What changes are required for the function to run.
lower_bound returns an iterator, not an index of the element found. You'll need to use std::distance to retrieve the index, but usually, the iterator is what you need/want for further processing.
Also note an index is usually returned as an std::size_t, not an int as you seem to assume.
As pointed in previous answers, lower_bound returns an iterator.
The type of x in lower_bound is not clear, x should also be the same type as that of the type in the container and compare function.
In this case, the type of x should be arr.
I have a struct as below :
typedef struct
{
vector<int[6]> swaps;
int score;
}State;
Which I then instantitate
State s1;
int s1arr[]={1,2,3,4,5,6};
s1.swaps.push_back(s1arr); //this is line number 164 in the error
s1.score=23;
Everything below is a huge error. I could not find a similar error anywhere except a location(not on stack overflow where also it was unanswered). The error occurs when i push back into s1.swaps . I would be thankful if someone could help me figure out the error
Error Log
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\vector:69:0,
from SessionOrganizer.h:13,
from SessionOrganizer.cpp:7:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc: In instantiation of
'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator
, const _Tp&) [with _Tp = int [6]; _Alloc = std::allocator<int [6]>; std::vector
<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int (*)[6], std::vector<i
nt [6]> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int (*)[6]]':
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_vector.h:913:28: required
from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = in
t [6]; _Alloc = std::allocator<int [6]>; std::vector<_Tp, _Alloc>::value_type =
int [6]]'
SessionOrganizer.cpp:164:33: required from here
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:329:19: error: array
must be initialized with a brace-enclosed initializer
_Tp __x_copy = __x;
^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:335:16: error: invali
d array assignment
*__position = __x_copy;
^
In file included from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32\bits\c+
+allocator.h:33:0,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\allocator.
h:46,
from c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\string:41,
from SessionOrganizer.h:10,
from SessionOrganizer.cpp:7:
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ext\new_allocator.h: In instantiation
of 'void __gnu_cxx::new_allocator<_Tp>::construct(__gnu_cxx::new_allocator<_Tp>
::pointer, const _Tp&) [with _Tp = int [6]; __gnu_cxx::new_allocator<_Tp>::point
er = int (*)[6]]':
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ext\alloc_traits.h:216:9: required
from 'static void __gnu_cxx::__alloc_traits<_Alloc>::construct(_Alloc&, __gnu_cx
x::__alloc_traits<_Alloc>::pointer, const _Tp&) [with _Tp = int [6]; _Alloc = st
d::allocator<int [6]>; __gnu_cxx::__alloc_traits<_Alloc>::pointer = int (*)[6]]'
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_vector.h:906:34: required
from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = in
t [6]; _Alloc = std::allocator<int [6]>; std::vector<_Tp, _Alloc>::value_type =
int [6]]'
SessionOrganizer.cpp:164:33: required from here
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\ext\new_allocator.h:130:9: error: par
enthesized initializer in array new [-fpermissive]
{ ::new((void *)__p) _Tp(__val); }
^
Makefile:2: recipe for target 'all' failed
You shouldn't store C array in vector, it's neither copyable, nor movable, nor assignable. You can use std::array if you can use C++11, or boost::array if not. You also can use just std::vector<std::vector<int> >.
vector<array<int, 6> > swaps;
std::vector is making assignments of its elements internally, this is not defined for arrays. The interesting part of your error is:
error: invalid array assignment
you will get the same error if you write:
int nn[10];
int nn2[10];
nn = nn2;
this gives:
main.cpp:21:8: error: invalid array assignment
nn = nn2;
^
so either use vector of vector-s or vector of std::array-s
Since you can't use c++11, either use boost::array as others have suggested, or use a vector of vectors, and use the array to initialize the inner vector.
Here is the vector of vectors solution - it is similar in structure to what you wanted.
#include <vector>
struct State {
std::vector<std::vector<int> > swaps; // Note the space betweeen the
// angle brackets due lack of c++11
int score;
};
int main(int argc, char** argv)
{
int s1arr[] = {1, 2, 3, 4, 5, 6};
State s1;
s1.swaps.push_back(
std::vector<int>(s1arr, // Start of s1arr
s1arr + sizeof(s1arr) / sizeof(s1arr[0]))); // End of s1arr
}
Admittedly, this is not as clean as what you had initially, however, this can be made cleaner as follows (if you don't mind giving the array to the constructor):
#include <vector>
struct State {
std::vector<std::vector<int> > swaps;
int score;
// Default constructor so you can still use the old way
State {};
// Constructor which will take an array and create the vector
template<size_t N>
State(const int (&array)[N])
{
swaps.push_back(std::vector<int>(array, array + N));
}
};
int main(int argc, char** argv)
{
int s1arr[] = {1, 2, 3, 4, 5, 6};
State s1(s1arr); // Creates swaps vector
// Print out the internal swaps vector
for (int i = 0; i < s1.swaps[0].size(); ++i) {
std::cout << s1.swaps[0][i] << "\n";
}
}
In my code I have:
struct datapoint
{
double energy;
double probability;
};
Which is later put into a vector like so:
std::vector<datapoint> spectrum(71,0);
spectrum[0].energy = 0.937729;
spectrum[0].probability = 0.0022582628449311468;
spectrum[1].energy = 1.875458;
spectrum[1].probability = 0.0033531784328108922;
...
However, at compile time, for the line
std::vector<datapoint> spectrum(71,0);
I receive the error
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h: In member function âvoid std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_Integer, _Integer, std::__true_type) [with _Integer = int, _Tp = datapoint, _Alloc = std::allocator<datapoint>]â:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:303: instantiated from âstd::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = int, _Tp = datapoint, _Alloc = std::allocator<datapoint>]â
/src/PrimaryGeneratorAction.cc:74: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:991: error: no matching function for call to âstd::vector<datapoint, std::allocator<datapoint> >::_M_fill_initialize(size_t, int&)â
I'm a bit confused as I have done this before.
You are trying to invoke the fill-constructor of vector:
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
But 0 is not a valid value of type datapoint.
struct datapoint
{
double energy;
double probability;
datapoint():energy(0.0), probability (0.0)
{}
};
then
std::vector spectrum(71);
Have fun,
I need to insert a 1D array into the hashset.
But I got error while compiling.
#include <stdio.h>
#include <stdlib.h>
#include <hash_set.h>
using namespace std;
int hash_comp(const int* state1,const int* state2) {
int result = 0;
for (i = 0; i < 16; i++)
{
if (state1[i] != state2[i]) {
result = -1;
}
}
return result;
}
struct eqArray
{
bool operator()(const int* a1,const int* a2) const
{
return hash_comp(a1,a2) == 0;
}
};
hash_set<int*,hash<int*>,eqArray> closelist;
int main(int argc, char** argv)
{
const int sn[16] = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15};
closelist.insert(sn);
return 0;
}
/usr/include/c++/4.2.1/ext/hashtable.h: In member function 'size_t __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::_M_bkt_num_key(const _Key&, size_t) const [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]':
/usr/include/c++/4.2.1/ext/hashtable.h:599: instantiated from 'size_t __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::_M_bkt_num(const _Val&, size_t) const [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hashtable.h:1006: instantiated from 'void __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::resize(size_t) [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hashtable.h:437: instantiated from 'std::pair<__gnu_cxx::_Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>, bool> __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::insert_unique(const _Val&) [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hash_set:197: instantiated from 'std::pair<typename __gnu_cxx::hashtable<_Value, _Value, _HashFcn, std::_Identity<_Tp>, _EqualKey, _Alloc>::const_iterator, bool> __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc>::insert(const typename __gnu_cxx::hashtable<_Value, _Value, _HashFcn, std::_Identity<_Tp>, _EqualKey, _Alloc>::value_type&) [with _Value = int*, _HashFcn = __gnu_cxx::hash<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
src/ods2.cpp:677: instantiated from here
If you use a std::array<int, 16> instead of int*, all your problems will go away. If you have no C++11 compiler, you can use boost::array instead. Also, replace hash_set with unordered_set.
It appears there is no specialization of std::hash for std::arrays, so I wrote my own:
#include <unordered_set>
#include <array>
namespace std
{
template<typename T, size_t N>
struct hash<array<T, N> >
{
typedef array<T, N> argument_type;
typedef size_t result_type;
result_type operator()(const argument_type& a) const
{
hash<T> hasher;
result_type h = 0;
for (result_type i = 0; i < N; ++i)
{
h = h * 31 + hasher(a[i]);
}
return h;
}
};
}
std::unordered_set<std::array<int, 16> > closelist;
int main()
{
std::array<int, 16> sn = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15};
closelist.insert(sn);
}
You didn’t post the actual error message, only the trace. That said, it’s probably because your set uses non-const int* while your data is const.
That said, I’d suggest using unordered_set instead of hash_set(either from std::tr1 if your compiler supports that, or from std if your compiler supports C++11 or from Boost), and heed Fred’s advice of using an {std,boost}::array instead of a raw pointer.
I don't think that there exists a specialized hash<int*>. I added this:
namespace __gnu_cxx{ //I'm not sure what compiler version you used,
//mine wanted this
template<>
struct hash<const int*>{
size_t operator()(const int*a) const{
size_t r = 0;
for (int i=0;i<16;i++)
r = (r<<1) ^ a[i]; //not sure if it makes sense as a hash.
return r;
}
};
}
I also put in some consts and it compiles.