I'm wondering how can i do something like this ? Using template<typename T> with typedef ?
template <typename T>
typedef bool (*cmp_func)(T i0, T i1); // <- syntax error here
I'm trying to sort items of a template type.
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <ctime>
using namespace std;
typedef bool (*cmp_func)(int i0, int i1);
template<typename T>
void print_array(int n, T *x)
{
cout << "[";
for (int i = 0; i < n; ++i) {
cout << setw(3) << x[i];
}
cout << " ]\n";
}
template <typename T>
bool less_than(T i0, T i1) { return i0 < i1; }
template <typename T>
bool greater_than(T i0, T i1) { return i0 > i1; }
template <typename T>
bool is_sorted(int n, T *x, cmp_func cmp)
{
for (int i = 1; i < n; ++i)
if ((*cmp)(x[i], x[i-1]))
return false;
return true;
}
template <typename T>
void exchange(T* x, int i, int j)
{
T t = x[i];
x[i] = x[j];
x[j] = t;
}
template <typename T>
void insertion_sort(T *x, int l, int r, cmp_func cmp)
{
for (int i = l+1; i <= r; ++i) {
for (int j = i; j > l; --j){
if ((*cmp)(x[j], x[j-1]))
exchange(x, j, j-1);
cout << " ";
print_array(r-l+1, x+l);
}
}
}
template <typename T>
void insertion_sort2(T *x, int l, int r, cmp_func cmp)
{
for (int i = r; i > l; --i)
if ((*cmp)(x[i], x[i-1]))
exchange(x, i, i-1);
for (int i = l+2; i <= r; ++i) {
int j = i;
int v = x[i];
while((*cmp)(v, x[j-1])) {
x[j] = x[j-1];
--j;
}
x[j] = v;
cout << " ";
print_array(r-l+1, x+l);
}
}
template <typename T>
void fill_random(T n, T *x)
{
const int M = 100;
srand(time(0));
for (int i = 0; i < n; ++i)
x[i] = rand() % M;
}
int main(int argc, char **argv)
{
const int N = 10;
int x[N];
fill_random(N, x);
print_array(N, x);
insertion_sort(x, 0, N-1, &less_than);
print_array(N, x);
if (is_sorted(N, x, &less_than))
cout << "SORTED\n";
else
cout << "NOT SORTED\n";
return EXIT_SUCCESS;
}
Typedefs cannot be templates. C++11 using aliases, however, can be:
template <typename T>
using cmp_func = bool (*)(T i0, T i1);
The pre-C++11 workaround is to create a template struct that has a type typedef:
template <typename T>
struct cmp_func {
typedef bool (*type)(T i0, T i1);
};
Which is then referenced as typename cmp_func<int>::type for example.
Related
In main function I calls the Choice function. The goal is to choose the sort type with the order of increase or decrease.
I calls Choice to receive the address of two IsBigger and Interchange functions.
Here is the code
#include <iostream>
using namespace std;
template <class T>
void Swap(T *a, T *b)
{
T temp = *a;
*a = *b;
*b = temp;
}
template <class T>
void Interchange(T a[], int n, bool(*Cmp)(T, T))
{
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++)
if (Cmp(a[i], a[j]))
Swap(&a[i], &a[j]);
}
template <class T>
void Insertion(T a[], int n, bool(*Cmp)(T, T))
{
int x, j;
for (int i = 0; i < n; i++)
{
x = a[i]; j = i - 1;
while (j >= 0 && !Cmp(a[j],x))
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = x;
}
}
template <class T>
bool IsBigger(T a, T b)
{
return a > b;
}
template <class T>
void Choice(T a[], int n, bool(*Cmp)(T, T), void(*Sort)(T*, int, bool*))
{
Sort(a, n, Cmp);
}
int main()
{
int a[] = { 3,4,1,5 };
Choice<int>(a, 4, &IsBigger, &Interchange);
return 0;
}
In main function, function Choice has error when it calls IsBigger and Interchange. The error is "no instance of function template "Choice" matches the argument list"
I don't know what am I wrong. Please help me. Thanks a lot
I am very new to object oriented programming and C++. I have been working on a matrix class and squarematrix class and have been running into some problems that I can't seem to figure out. The error code I have been getting is:
C2784:
'matrix<T,m,k> operator *(matrix<T,m,n> &,matrix<T,n,k> &)': could not
deduce template argument for 'matrix<T,m,n> &' from
'std::vector<std::vector<double,std::allocator<_Ty>>,std::allocator<std::vector<_Ty,std::allocator<_Ty>>>>'
I am really unsure why, because I have had other parts of my code work. The error is reported in the line with "product.elements = product.elements * elements;"
//Source.cpp
#include"Squarematrix.h"
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<double> a = { 1, 2,4,5,6};
squarematrix<double,2> N;
N.assign(a);
cout << N << N.pow(2)<< endl;
return(0);
}
//Matrix.h
#ifndef _Matrix_
#define _Matrix_
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
template<class T, int m, int n>
class matrix {
public:
vector<vector<T>> elements;
int nrow;
int ncol;
matrix();
matrix(matrix<T, m, n>&);
};
template<class T, int m, int n>
matrix<T, m, n>::matrix() {
vector<T>temp(n, 0);
elements.assign(m, temp);
nrow = m; //m=0
ncol = n; //n=0
}
template<class T, int m, int n>
matrix<T, m, n>::matrix(matrix<T, m, n>& a) {
elements = a.elements;
nrow = m;
ncol = n;
}
template<class T, int m, int n, int k>
matrix<T, m, k> operator*(const matrix<T, m, n>& a, const matrix<T, n, k>& b) {
matrix<T, m, k> product;
for (int i = 0; i < m; i++) {
for (int j = 0; j < k; j++) {
for (int h = 0; h < n; h++)
product.elements[i][j] += a.elements[i][h] * b.elements[h][j];
}
}
return product;
}
template<class T, int m, int n>
ostream& operator<< (ostream& o, const matrix<T, m, n>& input) {
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j)
o << input.elements[i][j] << " ";
o << endl;
}
return o;
}
#endif _Matrix_
//Squarematrix.h
#ifndef _Squarematrix_
#define _Squarematrix_
#include "Matrix.h"
#include <iostream>
#include <vector>
using namespace std;
template<class T, int n>
class squarematrix : public matrix<T, n, n> {
public:
squarematrix();
squarematrix(squarematrix<T, n>&);
squarematrix<T, n> pow(int); //calculate A^k
};
template<class T, int n>
squarematrix<T, n>::squarematrix(){
vector<T>temp(n, 0);
elements.assign(n, temp);
nrow = n; //n=0
ncol = n; //n=0
}
template<class T, int n>
squarematrix<T, n>::squarematrix(squarematrix<T, n>& a){
elements = a.elements;
nrow = n;
ncol = n;
}
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product;
product.elements = elements;
for (int power = 2; power <= k; power++) {
product.elements = product.elements * elements;
}
return product;
}
#endif _Squarematrix_
You don't need nrow and ncol - they're template parameters and known at compile time.
But that's not the problem - you're multiplying std::vector where you should be multiplying squarematrix:
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product = unit_matrix<T, n>();
for (int power = 1; power <= k; power++) {
product = product * *this;
}
return product;
}
where I've used a fictitious function that creates a unit matrix.
Writing that function left as an exercise.
this code product.elements = product.elements * elements expresses that you want use two std::vector to multiply, but you don't support the operator * operation with two parameters whose type is std::vector.
In your code, you support a operator * operation with type matrix, so if you want use it, you should change the code product.elements = product.elements * elements to product.elements = (product * *this).elements
that will be OK.
so the code of the member function pow of class Squarematrix is:
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product;
product.elements = this->elements;
for (int power = 2; power <= k; power++) {
product.elements = (product * *this).elements;
}
return product;
}
at last , #endif is the end of some predefined and don't follow some macro, otherwise, the compiler will throw some warnings or errors.
I have been searching for weeks on how to come up with piece of code which I could applied the cartesian product. Let's say I have two arrays :
int M[2]= {1,2};
int J[3] = {0,1,2};
So the code will takes those two arrays in apply the rule M X J
therefore we will have the pairs (1,0)(1,1)(1,2)(2,0)(2,1)(2,2) and I want the new result to be saved into a new array where each index in the array contains a pair , for example c[0] = (1,0).
Help please :(
Here is an implementation where the sequences of values is a parameter (rather than pre-known as in all the other implementations):
void CartesianRecurse(vector<vector<int>> &accum, vector<int> stack,
vector<vector<int>> sequences, int index)
{
vector<int> sequence = sequences[index];
for (int i : sequence)
{
stack.push_back(i);
if (index == 0)
accum.push_back(stack);
else
CartesianRecurse(accum, stack, sequences, index - 1);
stack.pop_back();
}
}
vector<vector<int>> CartesianProduct(vector<vector<int>> sequences)
{
vector<vector<int>> accum;
vector<int> stack;
if (sequences.size() > 0)
CartesianRecurse(accum, stack, sequences, sequences.size() - 1);
return accum;
}
main() {
vector<vector<int>> sequences = { {1,2,7},{3,4},{5,6} };
vector<vector<int>> res = CartesianProduct(sequences);
// now do something with the result in 'res'.
}
#include <iostream>
#include <iterator>
#include <vector>
#include <utility>
#include <tuple>
template<typename Range1, typename Range2, typename OutputIterator>
void cartesian_product(Range1 const &r1, Range2 const &r2, OutputIterator out) {
using std::begin; using std::end;
for (auto i = begin(r1);i != end(r1); ++i) {
for (auto j = begin(r2); j != end(r2); ++j) {
*out++ = std::make_tuple(*i, *j);
}
}
}
int main() {
std::vector<int> a{1,2,3};
std::vector<char> b{'a','b','c','d','e','f'};
std::vector<std::tuple<int, char>> c;
cartesian_product(a, b, back_inserter(c));
for (auto &&v : c) {
std::cout << "(" << std::get<int>(v) << "," << std::get<char>(v) << ")";
}
}
Prints:
(1,a)(1,b)(1,c)(1,d)(1,e)(1,f)(2,a)(2,b)(2,c)(2,d)(2,e)(2,f)(3,a)(3,b)(3,c)(3,d)(3,e)(3,f)
And you can also apply the function to your case:
template<typename T, int N> constexpr int size(T (&)[N]) { return N; }
int main() {
int M[2] = {1,2};
int J[3] = {0,1,2};
std::tuple<int, int> product[size(M) * size(J)];
cartesian_product(M, J, product);
for (auto &&v : product) {
std::cout << "(" << std::get<0>(v) << "," << std::get<1>(v) << ")";
}
}
The output is:
(1,0)(1,1)(1,2)(2,0)(2,1)(2,2)
http://coliru.stacked-crooked.com/a/3ce388e10c61a3a4
Here is an simple example of implementing Cartesian product using vector. Vectors are much better choice as we do not need to worry about its size as it dynamically changes it.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
int main() {
int M[2]= {1,2};
int J[3] = {0,1,2};
vector<pair<int,int>> C;
for (int i = 0; i < sizeof(M)/sizeof(M[0]); i++)
{
for (int j = 0; j < sizeof(J)/sizeof(J[1]); j++)
{
C.push_back(make_pair(M[i],J[j]));
}
}
/*
for (vector<int>::iterator it = C.begin(); it != C.end(); it++)
{
cout << *it << endl;
}
*/
for (int i = 0; i < C.size(); i++)
{
cout << C[i].first << "," << C[i].second << endl;
}
}
Here is the link where I implemented the above code. Although I wouldn't post solution directly relating to your question, links posted in the comments already contains answer which is why I posted.
I think using of c++ two-dimensional arrays is a very bad idea, but if you want, you probably could use this code
#include <iostream>
int** cartesian_prod( int* s1, int* s2, int s1size, int s2size )
{
int ressize = s1size*s2size;
int** res = new int*[ressize];
for ( int i = 0; i < s1size; i++ )
for ( int j = 0; j < s2size; j++ )
{
res[i*s2size+j] = new int[2];
res[i*s2size+j][0] = s1[i];
res[i*s2size+j][1] = s2[j];
}
return res;
}
int main() {
int M[2]= {1,2};
int J[3] = {0,1,2};
int** res;
int Msize = sizeof(M)/sizeof(M[0]);
int Jsize = sizeof(J)/sizeof(J[1]);
res = cartesian_prod(M, J, Msize, Jsize);
for ( int i = 0; i < Msize*Jsize; i++ )
std::cout << res[i][0] << " " << res[i][1] << std::endl;
for (int i = 0; i < Msize*Jsize; i++)
delete[] res[i];
delete[] res;
return 0;
}
But it is much better to deal with std::vector - it much faster (in terms of development time) and will save you from many errors.
Solution without for loops.
#include<array>
#include<iostream>
#include<tuple>
#include<utility>
template
<typename T, typename Tuple, std::size_t... I>
auto cartesian_product_base(
const T& a,
const Tuple& t,
std::index_sequence<I...>) {
return std::make_tuple(std::make_pair(a, std::get<I>(t))...);
}
template
<typename T, typename... Ts, std::size_t... I>
std::array<T, sizeof...(Ts) + 1> to_array(std::tuple<T, Ts...> t, std::index_sequence<I...>) {
return {std::get<I>(t)...};
}
template
<typename Tuple1, typename Tuple2, std::size_t... I>
auto cartesian_product_impl(
const Tuple1& t1,
const Tuple2& t2,
std::index_sequence<I...>) {
return std::tuple_cat(cartesian_product_base(
std::get<I>(t1),
t2,
std::make_index_sequence<std::tuple_size<Tuple2>::value>{})...);
}
template
<typename T1, std::size_t N1, typename T2, std::size_t N2>
auto cartesian_product(
const std::array<T1, N1>& a1,
const std::array<T2, N2>& a2) {
return to_array(
cartesian_product_impl(a1, a2, std::make_index_sequence<N1>{}),
std::make_index_sequence<N1 * N2>{});
}
using namespace std;
int main() {
array<int, 2> M = {1, 2};
array<int, 3> J = {0, 1, 2};
auto C = cartesian_product(M, J);
cout << C.size() << endl;
cout << "{";
for (size_t i = 0; i != C.size(); ++i) {
if (i != 0) {
cout << ", ";
}
cout << "(" << C[i].first << ", " << C[i].second << ")";
}
cout << "}" << endl;
}
This question already has an answer here:
How to get feedback on design [closed]
(1 answer)
Closed 8 years ago.
I am trying to write an implementation of std::vector to learn C++ and my implementation is slower than std::vector (see output).
I am wondering how I can improve it from any C++ experts. I saw this question (Why is std::vector so fast ( or is my implementation is too slow )) but his problem didn't help as the poster was using the wrong data structure.
I am asking how I can get it faster than std::vector.
vector.h
template <typename T>
class Vector {
public:
explicit Vector(const int n);
explicit Vector(const int n, const T& val);
T& operator[](const int i);
inline int const length();
inline void fill(const T& val);
private:
T* arr;
int len;
};
vector.cpp
#include "vector.h"
#include <iostream>
#include <algorithm>
using namespace std;
template <typename T>
inline void Vector<T>::fill(const T& val)
{
for (int i = 0; i < len; ++i) {
arr[i] = val;
}
}
template <typename T>
inline T& Vector<T>::sum()
{
T total = 0;
for (int i = 0; i < len; ++i) {
total += arr[i];
}
return total;
}
template <typename T>
Vector<T>::Vector(const int n) : arr(new T[n]()), len(n)
{
//cout << "Vector(n)" <<'\n';
}
template <typename T>
Vector<T>::Vector(const int n, const T& val) : arr(new T[n]), len(n)
{
//cout << "Vector(n, val)" <<'\n';
for (int i = 0; i < len; ++i) {
arr[i] = val;
}
}
template <typename T>
T& Vector<T>::operator[](const int i)
{
return arr[i];
}
template <typename T>
int const Vector<T>::length()
{
return len;
}
template class Vector<int>;
template class Vector<float>;
vector_test.cpp
#include "vector.h"
#include <iostream>
#include <chrono>
#include <vector>
using namespace std;
int main()
{
const int n = 2000000;
float sum = 0;
chrono::steady_clock::time_point start = chrono::steady_clock::now();
Vector<float> vec(n, 1);
sum = vec.sum();
chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
cout << "my vec sum = " << sum << '\n';
cout << "my vec impl took " << chrono::duration_cast<chrono::microseconds>(end - start).count()
<< "us.\n";
sum = 0;
start = chrono::steady_clock::now();
vector<float> vec2(n, 1);
for (int i = 0; i < n; ++i) {
sum += vec2[i];
}
end = std::chrono::steady_clock::now();
cout << "std::vec sum = " << sum << '\n';
cout << "stl::vec impl took " << chrono::duration_cast<chrono::microseconds>(end - start).count()
<< "us.\n";
}
Output:
my vec sum = 2e+06
my vec impl took 11040us.
std::vec sum = 2e+06
stl::vec impl took 8034us.
This is quite naive code since on every iteration the index is reevaluated (and you hope the optimizer will optimize it away):
for (int i = 0; i < len; ++i) {
arr[i] = val;
}
Here is a somewhat better way:
T* ptr = arr;
T* end = ptr + len;
while ( ptr < end ) *ptr++ = val;
However, a good compiler will indeed do this transformation.
The same idea can be applied to Sum():
template <typename T> inline T Vector<T>::sum()
{
T* ptr = arr;
T* end = ptr + len;
T total = 0;
while ( ptr < end ) total += *ptr++;
return total;
}
I am not sure if I am correctly overloading the << operator. The following code compiles without problem but does not produce the expected output.
#include <iostream>
#include "Matrix.h"
template<class T>
std::ostream& operator<<(std::ostream &out, const matrix<T> &A)
{
for(int ii = 0; ii << A.size(1); ii++)
{
for(int jj = 0; jj < A.size(2); jj++)
{
out << A(ii,jj) << " ";
}
out << std::endl;
}
return out;
}
int main(int argc, char** argv)
{
matrix<double> A = {{1.0, 2.0},{1.0,-1.0}};
cout << "\"" << A << "\"\n";
return 0;
}
The only output is:
""
Matrix.h
template<class T>
class matrix
{
public:
matrix(int rows, int cols);
matrix(const std::initializer_list<std::initializer_list<T>>& lst);
T& operator()(int i, int j);
T operator()(int i, int j) const;
int size(int n) const;
private:
int mRows;
int mCols;
std::vector<T> mData;
};
template<class T>
matrix<T>::matrix(int rows, int cols)
: mRows(rows),
mCols(cols),
mData(rows * cols)
{
}
template<class T>
matrix<T>::matrix(const std::initializer_list<std::initializer_list<T> >& lst)
: matrix(lst.size(), lst.size() ? lst.begin()->size() : 0)
{
int ii = 0, jj = 0;
for(const auto& l : lst)
{
for(const auto& v : l)
{
mData[ii*mCols + jj] = v;
jj++;
}
jj = 0;
ii++;
}
}
template<class T>
T& matrix<T>::operator()(int i, int j)
{
return mData[i*mCols + j];
}
template<class T>
T matrix<T>::operator()(int i, int j) const
{
return mData[i*mCols + j];
}
template<class T>
int matrix<T>::size(int n) const
{
if(n == 1)
{
return mRows;
}
else if(n == 2)
{
return mCols;
}
}
In your first for loop, you have:
for(int ii = 0; ii << A.size(1); ii++)
^
That should be a single < character:
for(int ii = 0; ii < A.size(1); ii++)
^
The reason why it wasn't doing anything is because the original loop resulted in a condition of 0 << A.size(1), which is 0, or false; thus, the outer loop is never executed.