I'm trying to use static array which size needs to be determined by given template values. However size will be constant across program runtime - thats why I decided not to use std::vector.
template<uint32_t BAR_WIDTH>
class Bar
{
//do_stuff...
Foo mapper[ [&]()->int{ uint32_t tmp = BAR_WIDTH / Foo:FOO_EDGE; return (BAR_WIDTH % 10 == 0) ? tmp : tmp + 1; }; ];
};
FOO_EGDE is const static value. IDE gives me a hint that
Array size expression must have an integer type instead of int(*)()
I wonder if I can make it work this way without using std::vector. Any advice is welcomed and appreciated.
The problem is, that you are using a lambda for determining the size of the array. If you leave it off and just use the ternary operator, it works:
int main() {
const bool z = true;
const int x = 5, y = 3;
int arr[z ? x : y];
return 0;
}
Ideone
As opposed to:
int main() {
const bool z = true;
const int x = 5, y = 3;
int arr[[&]() -> int { return z ? x : y; }];
return 0;
}
Ideone
As described here, lambda expressions can't be constexpr yet, and you can only declare the size of an array with a constexpr value (even then, you are not trying to invoke declared lambda (to invoke it - () is required at the end of declaration).
To work around such problem, you could use a private static constexpr method, and use the return value of it, for the array size declaration:
static constexpr uint32_t GetArraySize ()
{
uint32_t tmp = BAR_WIDTH / Foo::FOO_EDGE;
return (BAR_WIDTH % 10 == 0) ? tmp : tmp + 1;
}
Foo mapper[GetArraySize ()];
Related
I have Integer class that is supposed to simulate an integer mod n. Thus, it has constructors like:
Integer::Integer(int x)
: m(x), n(0)
{
}
Integer::Integer(int x, int y)
: n(y), m(x)
{
// if this->n greater than 1
if (this->n > 1)
{
// mod this->m by this->n
this->m %= this->n;
// if this->m is negative
if (this->m < 0)
{
// add this->n to it
this->m += this->n;
}
}
}
There is also Integer::inverse(), Integer::pow(int), which are needed for completeness of this question:
Integer Integer::inverse()
{
// Extended Euclidean Algorithm
int t = 0,
r = this->n,
newT = 1,
newR = this->m;
while (newR != 0)
{
int quotient = r / newR,
tCopy = t,
rCopy = r,
newTCopy = newT,
newRCopy = newR;
t = newT;
newT = tCopy - quotient * newTCopy;
r = newR;
newR = rCopy - quotient * newRCopy;
}
if (r > 1)
{
throw Integer(-1);
}
if (t < 0) t = t + this->n;
return Integer(t, this->n);
}
Integer Integer::squared()
{
return Integer(this->m * this->m, this->n);
}
Integer Integer::pow(int x)
{
// if x less than 0, return this->inverse().pow(-x)
if (x < 0) return this->inverse().pow(-x);
// if x is 0, return Integer(1)
if (x == 0) return Integer(1, this->n);
// if x is 1, return *this
if (x == 1) return *this;
// if x is 2, return this->squared()
if (x == 2) return this->squared();
// if x greater than 2
if (x > 2)
{
// if x is even
if (x % 2 == 0)
{
// return this->pow(x/2).squared()
return this->pow(x/2).squared();
}
// return this->pow(x/2).squared() * (*this)
return this->pow(x/2).squared() * (*this);
}
}
Problem I'm having is when I go to implement Integer::isQuadraticResidue() const:
bool Integer::isQuadraticResidue() const
{
// if this->n is zero
if (this->n == 0)
{
// this doesn't belong to Integers mod anything. check for perfect square instead
double baseSquareRoot = std::sqrt((double)this->m);
return (baseSquareRoot == (double)((int)baseSquareRoot));
}
// this is quadratic residue iff this->pow((this->n + 1) / 2) == Integer(1, this->n)
return (this->pow((n + 1) / 2).m == 1);
}
I get following error: error: passing ‘const Integer’ as ‘this’ argument of ‘Integer Integer::pow(int)’ discards qualifiers. I think it has everything to do with the const on the end. What do?
EDIT: Class header file looks something like:
#ifndef INTEGER_H
#define INTEGER_H
#include <iostream>
class Integer
{
public:
Integer(int);
Integer(int, int);
// functions
Integer inverse();
Integer squared();
Integer pow(int);
bool isQuadraticResidue() const;
Integer sqrt();
private:
int m, n;
};
#endif
This is an issue with const correctness, where a const function is trying to call a non-const function.
// ...
bool Integer::isQuadraticResidue() const;
Integer Integer::pow(int x);
// ....
In this situation, this is an Integer* in pow(), and a const Integer* in isQuadraticResidue(); this means that pow() can call isQuadraticResidue(), because it's legal to add CV-qualifiers, but not the other way around (because pow() would have to accept this as a non-qualified Integer*, losing the const qualifier).
This is unallowed, because allowing it would mean that isQuadraticResidue() breaks its guarantee that it won't modify the instance, whether directly or indirectly. While it itself doesn't change state, it assumes that pow() does change state, because pow() isn't also const (and thus doesn't promise not to change state). Due to this, isQuadraticResidue() is unable to call pow(), because doing so would risk breaking its guarantee.
Considering that, there are two solutions for this issue.
Remove const from isQuadraticResidue(). This would naively solve the problem, but isn't recommended, because then you wouldn't be able to reap the benefits of const correctness.
Make all member functions that don't modify Integer's logical state const, as well. This will require a bit more effort, but is overall safer. As they can then be called on a const Integer just as well as they can on an Integer, you will then be able to pass your instances around as const whenever they don't need to be modified, giving you a greater degree of safety.
Integer Integer::inverse() const;
Integer Integer::squared() const;
Integer Integer::pow() const;
This will need to be changed both in the functions' prototypes, and in their definitions.
the problem maybe you declared pow's this as non-const and trying to invoke it from isQuadraticResidue()const so in c++ it is not allowed to do so:
const this calls only member function whose this is const
you should either make pow's this const and as I guess it is bad idea becuase maybe you want to change some member data in it.
otherwise make isQuadraticResidue's this non-const
Integer pow(int x); // this is non const
bool isQuadraticResidue(); // this is not const
now everything is ok. as you can see after adding class declaration we get the error where!
Trying to understand lambdas in C++, what I do not understand is this:
int multiplier = 5;
auto timesFive = [multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2) << '\n'; // Prints 10
multiplier = 15;
std::cout << timesFive(2) << '\n'; // Still prints 2*5 == 10 (???) - Should it be 30?
When the program calls the timesFive() the second time, I expect the result to be 30. But why is the result Still prints 2*5 == 10, not prints 2*15 == 30? Perhaps the lambda function somehow cannot track the value of multiplier, even though we have already tried to capture it?
And what is the way to get the desired result?
You captured multiplier by value, which means it was copied into the lambda. You need to capture it by reference:
int multiplier = 5;
auto timesFive = [&multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2);
multiplier = 15;
std::cout << timesFive(2);
Lambdas are syntatic sugar for an unnamable class and the instance thereof. Sometimes expanding your code out to what this unnamable class can help understanding what is going on.
[ capture_list ]( arg_list ) -> return_value_clause_opt { body };
becomes very roughly (pseudo-code):
struct anonymous_type {
capture_list;
auto operator()( arg_list ) const -> return_value_clause_opt {
body
}
anonymous_type( capture_list_in ):capture_list(capture_list_in) {}
};
If you list a variable in capture_list by its plain name, it is copied into a copy within the anonymous class.
So your timesFive became
struct __secret_name__ {
int multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
It should be pretty clear that changing multiplier in the above code won't change the behavior of timesFive.
If you put a & in front of the name, a non-const reference is placed within the anonymous class.
struct __secret_name__ {
int& multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
now, changing multiplier will change the behavior of timesFive, because timesFive holds a reference to multiplier, not a copy of it.
Some details skipped above for brevity. The name __secret_name__ is only for exposition. The member variables of the lamba are not actually public. The lambda being trivially constructible is implementation defined even if its data is. Etc.
I am making a program where I have 2 vectors (clientvec and productslist) and I need to create a 2D boolean matrix where the columns is the size of productslist vector and the lines is the size of clientvec vector, but it gives me this error:
"expression must have a constant value"
Here is the code I used:
unsigned int lines = clientvec.size();
unsigned int columns = productslist.size();
bool matrixPublicity[lines][columns] = {false};
Pls help me..
Edit: I am new at c++ so assume I know nothing xD
Edit2: I already know for the answers that I cannot initialize an array with non constant values, now the question is how can I put them after initialize...
The error message is clear: :expression must have a constant value"
It means the array dimension cannot be of variable type. Only enums or pre-processor defined constants are valid.
See for more info:
Why can't I initialize a variable-sized array?
Edit: Since you mentioned you are new to C++, here is a piece of code that might help you:
#include <iostream>
#include <vector>
#include <bitset>
int main()
{
unsigned int lines = 10;
const unsigned int columns = 5;
std::vector<std::bitset<columns>> matrixPublicity;
matrixPublicity.resize(lines);
for(int i=0; i < lines; i++)
{
for(int j=0; j < columns; j++)
std::cout << matrixPublicity[i][j] <<' ';
std::cout<<'\n';
}
}
note that in this case, columns must be constant.
Edit 2: And if the size of lines are not the same, then you must stick to vector types:
typedef std::vector<bool> matrixLine;
std::vector<matrixLine> matrixPublicity;
now you can use resize method for the i-th line of the matrix, e.g.
matrixPublicity[1].resize(number_of_columns_in_line_2);
What you are trying to do would be the same as this:
std::vector<unsigned int> v1 { 1, 2, 3, 4, 5 };
std::vector<unsigned int> v2 { 6, 7, 8, 9 };
bool mat[v1.size()][v2.size()] = false;
This is how the compiler will interpret it without the temporaries and this is invalid. When you declare an array of any type its size has to be known at compile time.
bool mat[2][3] = false; // still invalid
bool mat[2][3] = { false }; // Okay
const int x = 5;
const int y = 7;
bool mat[x][y] = false; // invalid
bool mat[x][y] = { false }; // okay
// Even this is invalid
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 4, 5, 6, 7 };
const std::size_t x1 = v1.size();
const std::size_t y1 = v2.size();
bool mat2[x1][y1] = { false }; // Still won't compile.
Value to declare an array must be a constant expression.
Instead of making an array as you have tried to do, you could make a class template that will construct a matrix like object for you. Here is what I have come up with, now the overall design or pattern of this template will fit your condition but the actual implementation to generate the internal matrix will depend on your data and what you intend.
#include <vector>
#include <iostream>
#include <conio.h>
template <class T, class U>
class Matrix {
private:
std::vector<T> m_lines;
std::vector<T> m_cols;
std::vector<U> m_mat;
std::size_t m_size;
std::size_t m_lineCount;
std::size_t m_colsCount;
public:
Matrix() {};
Matrix( const std::vector<T>& lines, const std::vector<T>& cols ) :
m_lines(lines),
m_cols(cols),
m_lineCount( lines.size() ),
m_colsCount( cols.size() )
{
addVectors( lines, cols );
}
void addVectors( const std::vector<T>& v1, const std::vector<T>& v2 ) {
m_lines = v1;
m_cols = v2;
m_lineCount = m_lines.size();
m_colsCount = m_cols.size();
for ( unsigned int i = 0; i < m_lineCount; ++i ) {
for ( unsigned int j = 0; j < m_colsCount); j++ ) {
// This will depend on your implementation and how you
// construct this matrix based off of your existing containers
m_mat.push_back(m_lines[i] & m_cols[j]);
}
}
m_size = m_mat.size();
}
std::size_t size() const { return m_size; }
std::size_t sizeRows() const { return m_lineCount; }
std::size_t sizelColumns() const { return m_colsCount; }
std::vector<U>& getMatrix() const { return m_mat; }
std::vector<T>& getLines() const { return m_lines; }
std::vector<T>& getColumns() const { return m_columns; }
bool operator[]( std::size_t idx ) { return m_mat[idx]; }
const bool& operator[]( std::size_t idx ) const { return m_mat[idx]; }
};
int main() {
std::vector<unsigned> v1{ 1, 0, 1, 1, 0 };
std::vector<unsigned> v2{ 0, 1, 1, 1, 0 };
Matrix<unsigned, bool> mat1( v1, v2 );
int line = 0;
for ( unsigned u = 0; u < mat1.size(); ++u ) {
line++;
std::cout << mat1[u] << " ";
if ( line == mat1.sizeRows() ) {
std::cout << "\n";
line = 0;
}
}
std::cout << "\nPress any key to quit.\n" << std::endl;
_getch();
return 0;
}
Output
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
With this template class you can create a matrix of any type U by passing in two vectors for type T. Now how you construct the matrix will be implementation dependent. But this class is reusable for different types.
You could have two vectors of type doubles, and construct a matrix of unsigned chars, or you could have two vectors of user defined class or struct types and generate a matrix of unsigned values. This may help you out in many situations.
Note: - This does generate a compiler warning, no errors though and it prints and displays properly, but the compiler warning generated by MSVS 2015 is warning C4800: unsigned int: forcing value to bool true or false (performance warning)
This is generated for I am doing a bit wise & operation on to unsigned values; but that is why I set my initial vectors to be passed to this class template's constructor to have all 1s & 0s as this is meant for demonstration only.
EDIT - I made an edit to the class because I noticed I had a default constructor and had no way to add vectors to it, so I added an extra member variable, and an addVectors function, and moved the implementation from the defined constructor to the new function and just ended up calling that function in the defined constructor.
Creating an array isn't that difficult :)
A matrix (2D/3D/...-array) is unfortunately a little bit different if you want to do it your way!
But first of all you should know about the stack and the heap!
Lets have a look at these 2:
Stack:
A stack variable/array/matrix/... is only valid between the nearest 2 -> {} <- which you normally call a "codeblock". The size of it was defined during the "compile time" (the time where the compiler translates your code into the machine language). That means the size of your array needs to be set.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
std::cin >> size;
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' which is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//this is not valid!
int intArray[size()] = {};
return 0;
}
Heap:
A heap variable/array/matrix/... is valid until you delete it. That also means that a heap var is created during the run-time(from starting your program until you close/stop it)! This is allows you to define it's size.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' whic is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//creating an array with a non-static size
//works like this:
//int can also be a 'bool'
int* intArray = new int[arraySize()];
// ^ the star means you are pointing to
//an adress inside of your memory which has
//the size of an int (per element)
//That's why they are called "pointers"!
//Right now it points to the beginning of the
//array.
// ^ the keyword "new" says that
//you are allocating memory on the heap.
// ^
//then you have to say which kind of array
//it is which is the same you gave the pointer
// ^
//now you give it the size of that array
//this time it can be return value or the size
//of a variable
//as I mentioned...you have to delete this array on your own
//if you dont do that your program will crash
//maybe not after starting but it will!
//SO NEVER NEVER NEVER... forget about it
delete intArray[];
//^ write delete
// ^
//then the name of your array
// ^
//at the end of it write these 2 brackets
//thex say you wanna remove the whole array!
//why? because you can also create/delete
//heap variables not only arrays.
return 0;
}
Creating a matrix on the heap is unfortunately not that easy.
But it is essential to know how a 1D-array works before going to further dimensions! That's why I did this tutorial!
Klick here to see how to create a matrix on the heap
Klick here to learn more about the heap
Klick here to choose the best result of this theme
I hope I could help you :)!
I've got the following code snippet:
int odd[] = { 1,3,5,7,9 };
int even[] = { 0,2,4,6,8 };
// returns a pointer to an array of five int elements
decltype(odd) *arrPtr(int i) {
return (i % 2) ? &odd : &even; // returns a pointer to the array
}
int main()
{
int *res1 = arrPtr(3);
decltype(odd) *res2 = arrPtr(3);
auto res3 = arrPtr(3);
}
For the first line I get the following error message:
int (*arrPtr(int i))[5]
returns a pointer to an array of five int elements
Error: a value of type "int (*)[5]" cannot be used to initialize an entity of type "int *"
Why can't int* be used to initialize my return value from arrayPtr()? I would have assumed that the compiler is doing an explicit conversion.
Furthermore, what would one use as return type (best practice)?
It seems odd is declared as an array of int:
int odd[5];
The type of odd is int[5] and taking the address (or adding a * to decltype(odd)) of this array yields an int(*)[5]. It seems, you actually want to use the decayed type of odd:
decltype(+odd) arrPtr(int i) {
return i % 2? odd: even;
}
int main() {
int* res1 = arrPtr(3);
decltype(+odd) res2 = arrPtr(3);
auto res3 = arrPtr(3)
}
Note this use of unary + which forces decay of the array to become a pointer to the first element of the array.
If you really mean to return a pointer to the array, you'd need to use a suitable type when capturing the result (assuming the original implementation):
int (*res1)[5] = arrPtr(3);
decltype(odd)* res2 = arrPtr(3);
auto res3 = arrPtr(3);
Note, that this is a pointer to an array of 5 int, i.e., you'd access an element of it using
(*res1)[3];
or
res1[0][3];
int (&)[5] can decay to int *, it is not the case for int (*)[5].
You may change your code to
decltype(odd)& arrPtr(int i) {
return (i % 2) ? odd : even; // returns the reference to the array
}
and then
int main()
{
int *res1 = arrPtr(3);
decltype(odd)& res2 = arrPtr(3); // int (&)[5]
auto res3 = arrPtr(3); // int*
const auto& res4 = arrPtr(3); // const int (&)[5]
}
I have some 2D arrays of a static size:
double quickStats[NUM_REPETITIONS][NUM_TRIALS];
double mergeStats[NUM_REPETITIONS][NUM_TRIALS];
double bstStats[NUM_REPETITIONS][NUM_TRIALS];
Later, I want a reference to one of them:
double stats[NUM_REPETITIONS][NUM_TRIALS];
if(i == 0) {
stats = quickStats;
}
else if(i == 1) {
stats = mergeStats;
}
else if(i == 2) {
stats = bstStats;
}
However, this does not work.
What can I do to do what I am trying to do without nested for loops to manually copy each element into the reference array?
I just need to read from stats, it is to avoid redundant code.
Thanks
Try this:
#define NUM_REPETITIONS 10
#define NUM_TRIALS 10
double quickStats[NUM_REPETITIONS][NUM_TRIALS];
double mergeStats[NUM_REPETITIONS][NUM_TRIALS];
double bstStats[NUM_REPETITIONS][NUM_TRIALS];
int main(){
double (* ptr)[NUM_TRIALS] =quickStats;
}
Create a pointer to it like this:
double (*stats)[NUM_REPETITIONS][NUM_TRIALS];
Since your dimensions are known at compile time you can use std::array<> which is more versatile and readable:
std::array<std::array<double, NUM_TRIALS>, NUM_REPETITIONS> stat;
References have to be initialized upon declaration so you cannot assign it later on. Your best bet is using a pointer or declare the reference inside the if branches.
constexpr unsigned int N = 100;
double a[N][N] = {0};
/* Pointer. In your case, N should be NUM_TRAILS here */
double (*a_ptr)[N] = a;
/* Specified Reference Type */
double (&a_ref)[N][N] = a;
/* C++11 Auto Reference */
auto &a_autoref = a;
Test here: Coliru