Creating an array of a class with arguments in constructor - c++

I'm trying to instantiate an array of a class where the constructor takes two arguments, and initialize it in the same line.
Conceptually, I want to do something like this:
foo::foo (int A, int B = 10)
{
V1 = A;
V2 = B;
}
foo Myfoo[3] = { (1, 100), (2, 300), (5, 100) };
// what I _don't_ want to do is create individual objects like this:
// foo Myfoo1(1, 100);
// foo Myfoo2(2, 300);
// foo Myfoo3(5, 100);
What I found is that when the constructor is called the arguments are not as expected. The B argument always shows up as the default value of 10. Just in tinkering I threw in additional arguments in the array initialization.
foo Myfoo[3] = { (0, 1, 100), (2, 300, 0), (0, 5, 100, 0) };
To my surprise it compiled without error, but I didn't pursue this too far, because it didn't make sense to me - but I was able to affect the problem
Does anyone have an idea on how I should code this? I've already worked around the problem but I'm curious how it should be done properly.

With the usage of (1, 100), you're just passing one int with value 100 to the constructor of foo. The comma-operator just discards the 1st operand, and returns the 2nd operand here. (It doesn't work in the way as you expected like foo Myfoo1(1, 100); or foo(1, 100);.)
You should use {} ( list initialization (since C++11) ) instead of (), i.e.
foo Myfoo[3] = { {1, 100}, {2, 300}, {5, 100} };

The cause of the problem has already been explaind by #songhuanyao.
I can think of the following ways to resolve the problem.
Option 1
Use {} instead of () to construct objects.
foo Myfoo[3] = { {1, 100}, {2, 300}, {5, 100}};
Option 2
Use foo explitly with () to construct objects.
foo Myfoo[3] = { foo(1, 100), foo(2, 300), foo(5, 100) };
Option 3
Use foo explitly with {} to construct objects.
foo Myfoo[3] = { foo{1, 100}, foo{2, 300}, foo{5, 100}};

We need to use {} instead of () and code is working as expected
#include<iostream>
using namespace std;
class Test
{
public:
Test(int a, int b = 10)
{
x = a;
y = b;
cout << "C-tor" << endl;
}
void show()
{
cout << " x = " << x << " y = " << y << endl;
}
private:
int x;
int y;
};
int main()
{
Test obj[3] = {{10,20},{30,40}, {50,60}};
obj[0].show();
obj[1].show();
obj[2].show();
return 0;
}
Above code produces expected output:
C-tor
C-tor
C-tor
x = 10 y = 20
x = 30 y = 40
x = 50 y = 60
I hope it helps!

Related

C++: array<> too many initializers

The following code is returning the compilation error below. I'm stuck understanding how there are too many initializers. This code works using vector<X>. Does anyone know why the error is being reported and how to resolve? Thanks
#include <iostream>
#include <array>
using namespace std;
struct X {
int x, y;
};
int main(int argc, char *argv[])
{
array<X,2> a0 = {{0,1}, {2,3}};
for (auto& p : a0) {
cout << p.x << endl;
cout << p.y << endl;
}
return 0;
}
Compilation:
g++ -pedantic -Wall test116.cc && ./a.out
test116.cc: In function ‘int main(int, char**)’:
test116.cc:11:34: error: too many initializers for ‘std::array<X, 2>’
array<X,2> a0 = {{0,1}, {2,3}};
Try
array<X,2> a0 = {{{0,1}, {2,3}}};
Note the extra set of braces.
It seems a bit odd but it's this way because the only member of array is the actual array:
template <class T, size_t N>
class array {
T val[N];
// ...
};
The constructors are all implicitly defined so that array ends up being a trivially constructable type.
You may use one of the following initializations because std::array is an aggregate that contains another aggregate as its data member.
array<X,2> a0 = { { { 0, 1 }, { 2, 3 } } };
array<X,2> a0 = { 0, 1, 2, 3 };
array<X,2> a0 = { { 0, 1, 2, 3 } };
array<X,2> a0 = { { 0, 1, { 2, 3 } } };
array<X,2> a0 = { { { 0, 1 }, 2, 3 } };
I found that my problem is related to the version of g++,9.4.0 is ok and 5.4.0 not.version of g++.By the way, the version of g++ is associated with the system version generally.

Define a enum-variabele after declaration

I'm learning enumerations. I have the following problem: I don't understand, why this works:
enum {fahrrad = 1, Auto = 2} einFahrzeug;
int main() {
einFahrzeug = fahrrad;
but this doesn't:
enum {fahrrad = 1, Auto = 2} einFahrzeug;
einFahrzeug = fahrrad;
int main() { ...
I would be very happy about an answer
You can't assign stuff to variables outside of a function. More simple example:
#include <iostream>
int x;
x = 42;
int main()
{
std::cout << x << '\n';
}
This gives:
prog.cpp:4:1: error: ‘x’ does not name a type
x = 42;
^
Try it with ideone.com: https://ideone.com/A1K06A

initialize array to 0 in constructor [duplicate]

This question already has answers here:
Zero-initializing an array data member in a constructor
(6 answers)
Closed 5 years ago.
In C this can be done easily by doing
int myArray[10] = { 0 }; // all elements 0
(taken from this answer)
My question is, is there a way similar (or same) in C++ which I can use to initialize the array to 0 in the constructor?
EDIT 1
I need to do the above using initialization list.
May be something like
struct aa
{
int i[10];
aa() : i {0}{}
};
Yes. Same syntax applies in C++, although it has a different name (list initialization, or in this case its special case, aggregate initialization).
However, in the member initialization list, you have to use the different syntax: myArray{}. Note that explicitly initializing the first element to 0 is unnecessary, since that is the default.
Here is an example how it can be done
struct A
{
A() : a{} {}
enum { N = 10 };
int a[N];
} a;
Or
struct A
{
A() : a{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } {}
enum { N = 10 };
int a[N];
} a;
for (int x : a.a) std::cout << x << ' ';
std::cout << std::endl;
Another approach is to use an object of type std::array. For example
#include <array>
//...
struct A
{
A()
{
a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}
enum { N = 10 };
std::array<int, N> a;
} a;
for (int x : a.a) std::cout << x << ' ';
std::cout << std::endl;

How to place partially initialized struct object into a vector?

I currently have struct where I initialize only two of three member. I purposefully do this since during the time of creation I am not sure what the value will be ( I actually am fine with it being just zero).
struct my_data {
my_data(int x_, int y_) {
x = x_;
y = y_;
}
int x;
int y;
double z = 0;
};
int main() {
std::vector<my_data> my_vec;
my_vec.resize(10);
my_vec[0] = {3,4};
}
When I do this I get error: no matching function for call .... _T1(std::forward<Args ..
Is there any way to avoid this error or should I have to include z also in as parameter in constructor.
You need a default constructor:
my_data() = default;
FWIW, you can make my_data easier to use by removing the constructor and the default value of z.
struct my_data {
int x;
int y;
double z;
};
int main() {
std::vector<my_data> my_vec;
my_vec.resize(10);
my_vec[0] = {}; // Same as = {0, 0, 0};
my_vec[1] = {3}; // Same as = {3, 0, 0};
my_vec[2] = {3, 4}; // Same as = {3, 4, 0};
my_vec[3] = {3, 4, 2.0};
}

VexCL: Index of maximum value in a vexcl vector

How can I find the index of the maximum value in a VexCL vector? I can find the maximum value:
int h[] = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, 5);
vex::copy(h, d);
vex::Reductor<int, vex::MAX> max(ctx.queue());
int m = max(d);
Which gives m = 5 but is there a way to find the index of the maximum value, ind = 3?
You will need to
encode both vector value and vector position in a vexcl expression, and
create custom functor for vex::Reductor that would reduce the above expression based on its first component.
Here is the working code:
#include <iostream>
#include <vector>
#include <vexcl/vexcl.hpp>
// This function converts two integers to cl_int2
VEX_FUNCTION(cl_int2, make_int2, (int, x)(int, y),
int2 v = {x, y};
return v;
);
// This struct compares OpenCL vector types by the first component.
struct MAX0 {
template <class Tn>
struct impl {
typedef typename vex::cl_scalar_of<Tn>::type T;
// Initial value.
static Tn initial() {
Tn v;
if (std::is_unsigned<T>::value)
v.s[0] = static_cast<T>(0);
else
v.s[0] = -std::numeric_limits<T>::max();
return v;
}
// Device-side function call operator
struct device : vex::UserFunction<device, Tn(Tn, Tn)> {
static std::string name() { return "MAX_" + vex::type_name<Tn>(); }
static std::string body() { return "return prm1.x > prm2.x ? prm1 : prm2;"; }
};
// Host-side function call operator
Tn operator()(Tn a, Tn b) const {
return a.s[0] > b.s[0] ? a : b;
}
};
};
int main(int argc, char *argv[]) {
vex::Context ctx( vex::Filter::Env );
std::vector<int> h = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, h);
// Create reductor based on MAX0 operation,
// then reduce an expression that encodes both value and position of a
// vector element:
vex::Reductor<cl_int2, MAX0> max(ctx);
cl_int2 m = max(make_int2(d, vex::element_index()));
std::cout << "max value of " << m.s[0] << " at position " << m.s[1] << std::endl;
}
This outputs
max value of 5 at position 3