C++17 parameter pack expansion with function parameter evaluation - c++17

I'm playing around with variadic templates and fold expressions, in particular doing type conversions to put into function parameters. My understanding is that to do something like:
template<T, typename ... Args>
void convertAndEvaluate(const vector<T>& convertibles)
{
size_t i = 0;
evaluate(some_function<Args>(convertibles[i++])...);
}
would not work as the order of evaluation of the function inputs are unspecified. Fold expressions can give the right evaluation order, however their result is parentheses enclosed and cannot be used as a function input. I can achieve the same result with index_sequences through another templated function, but I was wondering if there was a more concise way with C++17, something like using constexpr with pack expansion.
Toy example:
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
template<typename ... Args>
class Foo {
public:
Foo() {}
void just_print(const std::vector<int>& convertible)
{
size_t i = 0;
((cout << static_cast<Args>(convertible[i++]) << " "), ...);
cout << endl;
}
template<typename T,T... ints>
void expandEvaluate(const std::vector<int>& values, std::integer_sequence<T, ints...> int_seq)
{
eval(static_cast<Args>(values[ints])...);
}
void convert(const std::vector<int>& convertible)
{
expandEvaluate(convertible, std::make_index_sequence<sizeof...(Args)>());
}
void convert_wrong(const std::vector<int>& convertible)
{
size_t i = 0;
eval(static_cast<Args>(convertible[i++])...);
}
void eval(const Args&... values)
{
((cout << values << " "), ...);
cout << endl;
}
};
int main()
{
Foo<double, int, float, int, double> bar;
bar.eval(3, 4, 5, 6, 7);
bar.just_print({3, 4, 5, 6, 7});
bar.convert_wrong({3, 4, 5, 6, 7});
bar.convert({3, 4, 5, 6, 7});
return 0;
}
Output:
3 4 5 6 7
3 4 5 6 7
7 6 5 4 3
3 4 5 6 7
Edit:
In retrospect, my solution with the integer expansion necessitates expanding two parameter packs simultaneously, is this defined in the standard?

I think your solution (use of std::make_index_sequence/std::index_sequence to get indexes in right order) is a good one (and works also with C++14).
Starting from C++17 you can also use std::tuple/std::apply()
void convert2 (std::vector<int> const & cv)
{
std::size_t i{};
std::tuple t{ static_cast<Args>(cv[i++])... };
std::apply([=](auto ... args){ eval(args...); }, t);
}
but it's almost your std::make_index_sequence/std::index_sequence solution, wrapped by std::apply().

Related

Get size of an array in C++ 17 using pass by reference

Is there a way to find the size of an array, using pass by reference. The size function works well inside the main function.
#include <iostream>
#include <iterator>
using namespace std;
int hello(int arr[]){
cout<<arr<<endl;
//cout<<size(arr)<<endl;
}
int main(){
int arr[] = {1,2,3,4,6,7,2};
hello(arr);
cout<<arr<<endl;
cout<<size(arr)<<endl;
}
You are passing array by value so hello function takes as its parameter decayed type - int*.
When you pass array by reference, you need to pass one additional non-type template parameter which is length of array and is deduced, therefore inside hello you don't even use std::size to get array's length, just use N:
template<class T, size_t N>
int hello(T (&arr)[N])
{
cout<< size(arr) <<endl; // 7
cout << N << endl; // 7
return 0;
}
Once you pass an array to a function, it becomes a pointer, and there is no way to get the size from that (it will always report 4 or 8 bytes - the size of a pointer value!).
If you need to process an array in a func, you will need to pass in the size as an argument to the function.
#include <iostream>
#include <iterator>
using namespace std;
int hello(int arr[], size_t count)
{
for(size_t i = 0; i < count; ++i)
{
std::cout << arr[i] << std::endl;
}
}
int main(){
int arr[] = {1,2,3,4,6,7,2};
hello(arr, sizeof(arr) / sizeof(int));
return 0;
}
The better alternative in C++, is to use std::vector instead. (which will store the size as a member variable)
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
void hello(const std::vector<int>& arr)
{
for(size_t i = 0; i < arr.size(); ++i)
{
std::cout << arr[i] << std::endl;
}
}
int main(){
std::vector<int> arr = {1,2,3,4,6,7,2};
hello(arr);
return 0;
}

GLM: Multiplying vec3 by a 3x3 translation matrix gives weird results [duplicate]

This question already has answers here:
Multiplying a matrix and a vector in GLM (OpenGL)
(2 answers)
Closed 4 years ago.
I have a glm::mat3 constructed via the experimental glm::translate(mat3,vec2) function. However, using this matrix to modify a vec3 gives funky results. Here is a short program demonstrating:
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/matrix_transform_2d.hpp>
#include <iostream>
std::ostream& operator<< (std::ostream& o, const glm::vec3& vec){
return o << '(' << vec.x << ',' << vec.y << ',' << vec.z << ")\n";
}
int main(){
glm::mat3 translate = glm::translate(glm::mat3(1.), glm::vec2(-1.,-1.));
std::cout << glm::vec3(10.,10.,1.); //prints (10,10,1)
std::cout << glm::vec3(10.,10.,1.) * translate; //prints (10,10,-19)
}
What is wrong with my matrix that is causing it to modify the Z coordinate instead of translating it?
Your operations are in the wrong order; you want translate * glm::vec3(10, 10, 1).

How can I store a big matrix within the .cc file?

I am currently working on a Computer Vision / Machine Learning project for university. Sadly, they only allow us to upload one single file and restrict the computation time too much. Hence I need to compute the matrices on my machine and store them in the same file as the code (22500 rows, 1 col and 100 rows + 22500 col and 100 rows + 1 col). I already found a way to export the data (link), but I'm not sure how to initialize the matrix.
What I've tried
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float data[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat A;
// Something is wrong with this line
A = cv::Mat(1, 10, cv::CV_32FC1, data);
return 0;
}
When I compile it, I get:
main.cc: In function ‘int main(int, const char**)’:
main.cc:10:16: error: expected primary-expression before ‘(’ token
A = cv::Mat(1, 10, cv::CV_32FC1, data);
^
In file included from /usr/include/opencv2/core/core_c.h:47:0,
from /usr/include/opencv/cv.h:63,
from main.cc:1:
main.cc:10:28: error: expected unqualified-id before ‘(’ token
A = cv::Mat(1, 10, cv::CV_32FC1, data);
^
Second try
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float dataHeaderMat1[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat matrix1;
// Something is wrong with this line
cv::cvInitMatHeader( &matrix1, 10, 1, CV_64FC1, dataHeaderMat1);
return 0;
}
gives
main.cc:10:5: error: ‘cvInitMatHeader’ is not a member of ‘cv’
cv::cvInitMatHeader( &matrix1, 10, 1, CV_64FC1, dataHeaderMat1);
^
The following works to declare and initialize a matrix:
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float data[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat A;
// Something is wrong with this line
A = cv::Mat(1, 10, CV_32FC1, data);
return 0;
}
However, I'm not too sure if this is the best way for big arrays.
You can try to save image to header file, like this:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// uncomment for test
//#include "image.h"
int main(int argc, char **argv)
{
// This part creates header file from image.
Mat img=imread("D:\\ImagesForTest\\lena.jpg");
int w=img.cols;
int h=img.rows;
int channels=img.channels();
ofstream os("image.h");
os << "int rows=" << h << ";" << endl;
os << "int cols=" << w << ";" << endl;
os << "unsigned char d[]={" << endl;
for(int i=0;i<h;++i)
{
for(int j=0;j<w;++j)
{
if(i!=(w-1) || j!=(h-1))
{
Vec3b b=img.at<Vec3b>(i,j);
os << format("0x%02x,",b[0]);
os << format("0x%02x,",b[1]);
os << format("0x%02x,",b[2]);
}
}
}
Vec3b b=img.at<Vec3b>(w-1,h-1);
os << format("0x%02x,",b[0]);
os << format("0x%02x,",b[1]);
os << format("0x%02x",b[2]);
os << endl << "};" << endl;
os << "Mat I=Mat(rows,cols,CV_8UC3,d);" << endl;
os.close();
// To test uncomment commented part of code and comment uncommented.
// uncomment for test
/*
namedWindow("I");
imshow("I",I);
waitKey();
return 0;
*/
}
But be careful, not all IDEs likes such large files.

Can you improve this solution to interfacing OpenCV 2.4+ to Zxing 1D barcode reader

I didn't find this solution on the net, had to figure it myself. So, for benefit of others, I'm posing this as a "question":
Can you improve my working interface of OpenCV 2.4+ to the C++ version of Zxing 2.2 1D barcode reader?
Here's my working but perhaps improvable implementation below:
/**
* Gary Bradski, Reading 1D barcodes
* License BSD, (c) 2013
*
* Working example of how to call zxing using OpenCV 2.4+ cv::Mat
*
* Calling example, this one for 128 barcodes:
*
* Code128Reader cr; //Instantiate a zxing barcode reader, int this case for 128 barcodes,
* // but you can use any of their 1D or multi readers here
* ... by magic, I find, rectify and islotate a barcode into cv::Mat barcodeImage
* decode_image(&cr, barcodeImage); //Decode the isolated rectified barcode or fail
*
*/
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
//////////////ZXING BARCODE READER//////////////////////////////////////////
#include <zxing/LuminanceSource.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/oned/OneDReader.h>
#include <zxing/oned/EAN8Reader.h>
#include <zxing/oned/EAN13Reader.h>
#include <zxing/oned/Code128Reader.h>
#include <zxing/datamatrix/DataMatrixReader.h>
#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/aztec/AztecReader.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/Exception.h>
using namespace zxing;
using namespace oned;
using namespace datamatrix;
using namespace qrcode;
using namespace aztec;
class OpenCVBitmapSource : public LuminanceSource
{
private:
cv::Mat m_pImage;
public:
OpenCVBitmapSource(cv::Mat &image)
: LuminanceSource(image.cols, image.rows)
{
m_pImage = image.clone();
}
~OpenCVBitmapSource(){}
int getWidth() const { return m_pImage.cols; }
int getHeight() const { return m_pImage.rows; }
ArrayRef<char> getRow(int y, ArrayRef<char> row) const //See Zxing Array.h for ArrayRef def
{
int width_ = getWidth();
if (!row)
row = ArrayRef<char>(width_);
const char *p = m_pImage.ptr<char>(y);
for(int x = 0; x<width_; ++x, ++p)
row[x] = *p;
return row;
}
ArrayRef<char> getMatrix() const
{
int width_ = getWidth();
int height_ = getHeight();
ArrayRef<char> matrix = ArrayRef<char>(width_*height_);
for (int y = 0; y < height_; ++y)
{
const char *p = m_pImage.ptr<char>(y);
int yoffset = y*width_;
for(int x = 0; x < width_; ++x, ++p)
{
matrix[yoffset + x] = *p;
}
}
return matrix;
}
/*
// The following methods are not supported by this demo (the DataMatrix Reader doesn't call these methods)
bool isCropSupported() const { return false; }
Ref<LuminanceSource> crop(int left, int top, int width, int height) {}
bool isRotateSupported() const { return false; }
Ref<LuminanceSource> rotateCounterClockwise() {}
*/
};
void decode_image(Reader *reader, cv::Mat &image)
{
try
{
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
Ref<BinaryBitmap> bitmap(new BinaryBitmap(binarizer));
Ref<Result> result(reader->decode(bitmap, DecodeHints(DecodeHints::TRYHARDER_HINT)));//+DecodeHints::DEFAULT_HINT)));
cout << result->getText()->getText() << endl;
//Export the read barcode here
}
catch (zxing::Exception& e)
{
//Export your failure to read the code here
cerr << "Error: " << e.what() << endl;
}
}
Forgot to attribute what I started with. There is an out of date (will not compile) implementation using IplImages here:
http://www.idealsoftware.com/opensource/scan-1d-2d-barcodes-webcam-zxing-opencv-visual-c.html
This updates that solution so that it works with Zxing 2.2 and OpenCV 2.1+
I think you can avoid the matrix copy by replacing
Ref<OpenCVBitmapSource> source(new OpenCVBitmapSource(image));
With
Ref<LuminanceSource> source(new GreyscaleLuminanceSource(image.data, image.step, image.rows, 0, 0, image.cols, image.rows));

clang not working properly for C++ Exceptions

struct ZeroError{
int err;
ZeroError(int e){err = e;}
};
int div(int a,int b)
{
if (b == 0)throw int(10);
return a/b;
}
int main()
{
try{
int x = div(10,0);
cout<< x;
}
catch(int z){
cout<<z;
}
}
even though exception is caught when i run the program i am getting
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an
unusual way. Please contact the application's support team for more
information.
Try compiling with -fcxx-exceptions.
Did a little cleanup on your code, using div as a function name collided with one in stdlib.h. Also tried to make the error output more distinctive.
#include <iostream>
#include <exception>
using namespace std;
struct ZeroError{
int err;
ZeroError(int e){err = e;}
};
int divide(int a,int b)
{
if (b == 0)throw int(10);
return a/b;
}
int main()
{
try{
int x = divide(10,0);
cout << x << endl;
}
catch(int z){
cout << "Exception: " << z << endl;
}
}
Compiling with the flag seems to work great:
% clang++ -fcxx-exceptions foo.cc
% ./a.out
Exception: 10
% clang++ --version
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Resources