How to place partially initialized struct object into a vector? - c++

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};
}

Related

List initialization of const and array structure fields

Just recently started C++ programming for micro-controllers, and I've ran into situations* where it would be convenient to have a non-static const field on a struct that is always guaranteed to have a fixed value (same for every instance of the sturct, ever).
Given a struct
struct S {
const uint8_t c; // Should always be 42
char v;
uint32_t arr[4];
}
I'd like c to be a constant value, and the same constant value every time. I would love to be able to use the convenience of brace initializer lists, for setting v and the members of arr like
S some_var = {'v', { 0, 1, 2, 3 } };
Since I'd like c to be a constant, I'm under the impression that I have to use an initializer list for setting c, such as S() : c(42) {}, which works just fine, as long as I don't try to also initialize arr, in which case I'm lost on how the list should look like. Is this doable using C++11? (Also interested in an answer if this is not doable in C++11, but in some newer standard.)
Example code:
#include <stdio.h>
#include <stdint.h>
struct S {
const uint8_t c; // Should always be 42 on every instance
// of the struct due to hardware shenanigance
// (i.e. this struct is the representation of a register value)
char v;
uint32_t arr[4];
// This allows using "S s1;"
S() : c(42), v('a'), arr{} {}
// This allows using "S s2 = { 'v', 0, 1, 2, 3 };" works but it's clumsy:
S(uint32_t v, uint32_t arr0, uint32_t arr1, uint32_t arr2, uint32_t arr3) :
c(42), v(v), arr{ arr0, arr1, arr2, arr3 } {}
// I would like to do something along the lines of "S s2 = { 'v', { 0, 1, 2, 3 } };":
// S(uint32_t v, uint32_t arr[4] /*?*/) :
// c(42), v(v), arr{/*?*/} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
// Initialiation like this works with the line:12 signature:
S s2 = { 'v', 0, 1, 2, 3 };
// I'd like to initialize like this:
// S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
*Context on why I'd want to do this: This might seem like a weird thing to want, since if the value is always the same, why bother storing it? Well imagine that the struct in question is a bitfield which corresponds to the register of an IC with which the micro-controller communicates. These registers sometimes have "reserved" fields, and the datasheet specifies what value you must write into these fields. From a programmer's point of view, it would be convenient if I never had to deal with setting said bits manually.
C++11 gives you std::array which is like a raw array, but comes with none of the "negatives" (array decay, can't copy). Using that you can get exactly what you want like
struct S {
const uint8_t c = 42;
char v = 'a';
std::array<uint32_t, 4> arr{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::array<uint32_t, 4> arr) : v(v), arr{arr} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
which outputs
s1.c = 42
s1.v = 'a'
s1.arr[3] = 0
s2.c = 42
s2.v = 'v'
s2.arr[3] = 3
If you absoluytley have to have a raw array in S then your other option is to use a std::initializer_list in the constructor. That would look like
struct S {
const uint8_t c = 42;
char v = 'a';
uint32_t arr[4]{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::initializer_list<uint32_t> data) : v(v)
{
int i = 0;
for (auto e : data)
arr[i++] = e;
}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
And you get the same results as the code using std::array.

Creating an array of a class with arguments in constructor

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!

Force list initialization size of a matrix

I have designed a matrix class. Now I would like to initialize via list
Matrix3D m2{{1,2,3},{4,5,6},{7,8,9}};
instead of
Matrix3D m1(1,2,3,4,5,6,7,8,9);
I have added a static assert to force the size of the matrix which does not work.
How should I modify the constructor?
#include <iostream>
using namespace std;
class Matrix3D
{
int a11;
int a12;
int a13;
int a21;
int a22;
int a23;
int a31;
int a32;
int a33;
public:
Matrix3D(
int a11,
int a12,
int a13,
int a21,
int a22,
int a23,
int a31,
int a32,
int a33):
a11(a11),
a12(a12),
a13(a13),
a21(a21),
a22(a22),
a23(a23),
a31(a31),
a32(a32),
a33(a33)
{
}
Matrix3D(std::initializer_list<std::initializer_list<double>> listlist);
};
Matrix3D::Matrix3D(std::initializer_list<std::initializer_list<double>> listlist)
{
constexpr int rows = (int)(listlist.begin()).size();
constexpr int cols = (int)listlist.size();
static_assert(rows == 3, "");
static_assert(cols == 3, "");
a11=(listlist.begin()+0)[0];
a12=(listlist.begin()+0)[1];
a13=(listlist.begin()+0)[2];
a21=(listlist.begin()+1)[0];
a22=(listlist.begin()+1)[1];
a23=(listlist.begin()+1)[2];
a31=(listlist.begin()+2)[0];
a32=(listlist.begin()+2)[1];
a33=(listlist.begin()+2)[2];
}
int main() {
Matrix3D m1(1,2,3,4,5,6,7,8,9);
Matrix3D m2{{1,2,3},{4,5,6},{7,8,9}};
return 0;
}
I have added a static assert to force the size of the matrix which does not work.
Unfortunately for your situation std::initializer_list<Elem> is designed for a variable number of elements, which is why you cannot statically say anything about its size in the general case. The fact that its size member is constexpr is a red herring:
constexpr std::initializer_list<int> constant_expr = { 0, 2, 4, 6 };
// this is what a constexpr size member makes possible
static_assert( constant_expr.size() == 4 );
std::initializer_list<int> non_constant_expr = { 1, 3, 5 };
// this can't work
//static_assert( non_constant_expr.size() == 3 );
Function parameters are not constant expressions.
Instead, you would be better served by a type with a statically known number of elements. Array references can be suited to your needs:
class Matrix3D {
using index_type = int;
static constexpr index_type cols = 3;
using row_arg_type = int[cols];
public:
Matrix3D(row_arg_type const& row0, row_arg_type const& row1, row_arg_type const& row2);
// rest of class omitted
};
// number of rows and row width are statically enforced
Matrix3D m = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Coliru demo

sending more than integer to the C++ function as parameter [duplicate]

If I have a prototype that looks like this:
function(float,float,float,float)
I can pass values like this:
function(1,2,3,4);
So if my prototype is this:
function(float*);
Is there any way I can achieve something like this?
function( {1,2,3,4} );
Just looking for a lazy way to do this without creating a temporary variable, but I can't seem to nail the syntax.
You can do it in C99 (but not ANSI C (C90) or any current variant of C++) with compound literals. See section 6.5.2.5 of the C99 standard for the gory details. Here's an example:
// f is a static array of at least 4 floats
void foo(float f[static 4])
{
...
}
int main(void)
{
foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f}); // OK
foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); // also OK, fifth element is ignored
foo((float[3]){1.0f, 2.0f, 3.0f}); // error, although the GCC doesn't complain
return 0;
}
GCC also provides this as an extension to C90. If you compile with -std=gnu90 (the default), -std=c99, or -std=gnu99, it will compile; if you compile with -std=c90, it will not.
This is marked both C and C++, so you're gonna get radically different answers.
If you are expecting four parameters, you can do this:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(f);
}
But that is rather unsafe, as you could do this by accident:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2}; // uh-oh
foo(f);
}
It is usually best to leave them as individual parameters. Since you shouldn't be using raw arrays anyway, you can do this:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(std::vector<float>(f, f + 4)); // be explicit about size
// assert says you cannot do this:
foo(std::vector<float>(f, f + 2));
}
An improvement, but not much of one. You could use boost::array, but rather than an error for mismatched size, they are initialized to 0:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
boost::array<float, 4> f = {1, 2, 3, 4};
foo(f);
boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0}
foo(f2);
}
This will all be fixed in C++0x, when initializer list constructors are added:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4}); // yay, construct vector from this
// assert says you cannot do this:
foo({1, 2});
}
And probably boost::array as well:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4});
foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure,
// I don't know if they will do the check, if possible.
}
You can create a compound literal:
function ((float[2]){2.0, 4.0});
Although, I'm not sure why you want to go through the trouble. This is not permitted by ISO.
Generally, shortcuts like this should be avoided in favor of readability in all cases; laziness is not a good habit to explore (personal opinion, of course)
You can technically take reference to array, but you still can't create anonymous initializer list I think.
void func(int (&bla)[4])
{
int count = sizeof(bla)/sizeof(bla[0]);
// count == 4
}
int bla[] = {1, 2, 3, 4};
func(bla);
int bla1[] = {1, 2};
func(bla1); // <-- fails
For C++ way, look at boost::assign. Pretty neat way of filling in STL containers.
The bad news is that there is no syntax for that. The good news is that this will change with the next official version of the C++ standard (due in the next year or two). The new syntax will look exactly as you describe.
No, you cannot do that. I do not have the standard available here, so I cannot give an exact reference, but the closest thing to what you ask for is string constants, i.e.
function(char *);
function("mystring");
is treated by the compiler as
char * some_pointer = "mystring";
function(char *);
function(some_pointer);
There is no way for other types of variables to be treated this way.
Sadly, it only works with character arrays:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
you can write a builder class that would allow for about the same syntax
// roughly
template <typename C>
class Builder {
public:
template <typename T>
Builder(const T & _data) { C.push_back(_data); }
template <typename T>
Builder& operator()(const T & _data) {
C.push_back(_data);
return *this;
}
operator const C & () const { return data; }
private:
C data;
};
this way, you can use the class as
foo( const std::vector & v);
foo( Builder< std::vector >(1)(2)(3)(4) );
To add to the fun, you can use templates to make it variable in length.
template<std::size_t N>
int chars(const char(&r)[N]){
std::cout << N << ": " << r << std::endl;
return 0;
}
template<std::size_t N>
int floats(const float(&r)[N]){
std::cout << N << ":";
for(size_t i = 0; i < N; i++)
std::cout << " " << r[i];
std::cout << std::endl;
return 0;
}
int main(int argc, char ** argv) {
chars("test");
floats({1.0f, 2.0f, 3.0f, 4.0f});
return 0;
}
I asked OpenAI Codex, and it suggested this method:
func((uint8_t *) "\x12\x34\x56\x78\x9a\xbc")
and it works in embedded C90, while the compound literals did not (syntax error near '{', expected 'sizeof').
Not really much benefit compared to creating a local scoped array, though:
{
uint8 da[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
func(da);
}

How to pass a constant array literal to a function that takes a pointer without using a variable C/C++?

If I have a prototype that looks like this:
function(float,float,float,float)
I can pass values like this:
function(1,2,3,4);
So if my prototype is this:
function(float*);
Is there any way I can achieve something like this?
function( {1,2,3,4} );
Just looking for a lazy way to do this without creating a temporary variable, but I can't seem to nail the syntax.
You can do it in C99 (but not ANSI C (C90) or any current variant of C++) with compound literals. See section 6.5.2.5 of the C99 standard for the gory details. Here's an example:
// f is a static array of at least 4 floats
void foo(float f[static 4])
{
...
}
int main(void)
{
foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f}); // OK
foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); // also OK, fifth element is ignored
foo((float[3]){1.0f, 2.0f, 3.0f}); // error, although the GCC doesn't complain
return 0;
}
GCC also provides this as an extension to C90. If you compile with -std=gnu90 (the default), -std=c99, or -std=gnu99, it will compile; if you compile with -std=c90, it will not.
This is marked both C and C++, so you're gonna get radically different answers.
If you are expecting four parameters, you can do this:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(f);
}
But that is rather unsafe, as you could do this by accident:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2}; // uh-oh
foo(f);
}
It is usually best to leave them as individual parameters. Since you shouldn't be using raw arrays anyway, you can do this:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(std::vector<float>(f, f + 4)); // be explicit about size
// assert says you cannot do this:
foo(std::vector<float>(f, f + 2));
}
An improvement, but not much of one. You could use boost::array, but rather than an error for mismatched size, they are initialized to 0:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
boost::array<float, 4> f = {1, 2, 3, 4};
foo(f);
boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0}
foo(f2);
}
This will all be fixed in C++0x, when initializer list constructors are added:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4}); // yay, construct vector from this
// assert says you cannot do this:
foo({1, 2});
}
And probably boost::array as well:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4});
foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure,
// I don't know if they will do the check, if possible.
}
You can create a compound literal:
function ((float[2]){2.0, 4.0});
Although, I'm not sure why you want to go through the trouble. This is not permitted by ISO.
Generally, shortcuts like this should be avoided in favor of readability in all cases; laziness is not a good habit to explore (personal opinion, of course)
You can technically take reference to array, but you still can't create anonymous initializer list I think.
void func(int (&bla)[4])
{
int count = sizeof(bla)/sizeof(bla[0]);
// count == 4
}
int bla[] = {1, 2, 3, 4};
func(bla);
int bla1[] = {1, 2};
func(bla1); // <-- fails
For C++ way, look at boost::assign. Pretty neat way of filling in STL containers.
The bad news is that there is no syntax for that. The good news is that this will change with the next official version of the C++ standard (due in the next year or two). The new syntax will look exactly as you describe.
No, you cannot do that. I do not have the standard available here, so I cannot give an exact reference, but the closest thing to what you ask for is string constants, i.e.
function(char *);
function("mystring");
is treated by the compiler as
char * some_pointer = "mystring";
function(char *);
function(some_pointer);
There is no way for other types of variables to be treated this way.
Sadly, it only works with character arrays:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
you can write a builder class that would allow for about the same syntax
// roughly
template <typename C>
class Builder {
public:
template <typename T>
Builder(const T & _data) { C.push_back(_data); }
template <typename T>
Builder& operator()(const T & _data) {
C.push_back(_data);
return *this;
}
operator const C & () const { return data; }
private:
C data;
};
this way, you can use the class as
foo( const std::vector & v);
foo( Builder< std::vector >(1)(2)(3)(4) );
To add to the fun, you can use templates to make it variable in length.
template<std::size_t N>
int chars(const char(&r)[N]){
std::cout << N << ": " << r << std::endl;
return 0;
}
template<std::size_t N>
int floats(const float(&r)[N]){
std::cout << N << ":";
for(size_t i = 0; i < N; i++)
std::cout << " " << r[i];
std::cout << std::endl;
return 0;
}
int main(int argc, char ** argv) {
chars("test");
floats({1.0f, 2.0f, 3.0f, 4.0f});
return 0;
}
I asked OpenAI Codex, and it suggested this method:
func((uint8_t *) "\x12\x34\x56\x78\x9a\xbc")
and it works in embedded C90, while the compound literals did not (syntax error near '{', expected 'sizeof').
Not really much benefit compared to creating a local scoped array, though:
{
uint8 da[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
func(da);
}