Initializing inner struct in emplace_back() - c++

I have struct which contains array of inner struct. I want to use method emplace_back() of vector<my_struct>. But I cannot figure how could I initialize this struct correctly:
struct my_struct
{
struct
{
float x, y, z;
} point[3];
};
std::vector<my_struct> v;
v.emplace_back(
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}
);
This gives compilation error error: no matching function for call to ‘std::vector<main()::my_struct>::emplace_back(<brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>)
Is it possible to emplace_back this struct (I'm using C++17)? Should I write custom constructor?

how about this:
v.push_back(my_struct{{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}});

Related

What happened when I pass a nested braced-init-lists to constructor in C++?

I passed an nested braced-init-lists to class constructor:
#include <iostream>
#include <type_traits>
#include <variant>
#include <vector>
class NestedInteger final {
public:
NestedInteger(int i) : type_(INT), val_int_(i) {}
// NestedInteger(std::initializer_list<NestedInteger> ni) {
template <typename T>
NestedInteger(std::initializer_list<T> ni) {
for (auto it = ni.begin(); it != ni.end(); it++) {
val_vec_.push_back(*it);
}
}
private:
enum { INT, VECTOR } type_;
int val_int_;
std::vector<NestedInteger> val_vec_;
};
int main() {
NestedInteger ni1{1};
NestedInteger ni2{1, 2, 3};
NestedInteger ni3{{1}, 2, 3};
NestedInteger ni4{{1, 2, 3}};
NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
return 0;
}
And I got compilation error:
t.cpp:29:44: error: no matching function for call to ‘NestedInteger::NestedInteger(<brace-enclosed initializer list>)’
29 | NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
| ^
t.cpp:12:3: note: candidate: ‘template<class T> NestedInteger::NestedInteger(std::initializer_list<_Tp>)’
12 | NestedInteger(std::initializer_list<T> ni) {
| ^~~~~~~~~~~~~
t.cpp:12:3: note: template argument deduction/substitution failed:
t.cpp:29:44: note: candidate expects 1 argument, 2 provided
29 | NestedInteger ni5{{1, 2, 3}, {4, 5, 6, 7}};
...
I read the list initialization in cppreference here. And I can tell the expression belongs to the first syntax type:
T object { arg1, arg2, ... }; (1)
initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)
I can't understand the explanation about the effects.
Could you help to figure out:
Which item in the explanation does this case match?
Is this a non-deduced contexts described here?
By the way, if I change the template to specific type as the commented line, the compilation error disapeared.

Array initialization differences C++11

Is there a difference between using curly braces or the assignment operator while defining an array in C++11?
std::array<int, 2> a{1, 2}
// or
std::array<int, 2> b{{1, 2}}
and
std::array<int, 2> = a{1, 2}

How to initialize std::array in class definition?

Since C++11, it is possible to initialize member variables in class definitions:
class Foo {
int i = 3;
}
I know I can initialize an std::array like this:
std::array<float, 3> phis = {1, 2, 3};
How can I do this in a class definition? The following code gives an error:
class Foo {
std::array<float, 3> phis = {1, 2, 3};
}
GCC 4.9.1:
error: array must be initialized with a brace-enclosed initializer
std::array<float, 3> phis = {1, 2, 3};
^ error: too many initializers for 'std::array<float, 3ul>'
You need one more set of braces, which is non-intuitive.
std::array<float, 3> phis = {{1, 2, 3}};

POD type initialization using initialization list does not work

I have defined a POD type as below:
template<typename kernelEntryT, size_t kernelRowSize, size_t kernelColSize>
class ImageProcessing::Kernel {
kernelEntryT kernelMatrix[kernelRowSize][kernelColSize];
};
int main(){
ImageProcessing::Kernel<int,3,3> k = {{0,0,0},{0,1,0},{0,0,0}};
}
It does not compile, and tell me:
error: could not convert ‘{{0, 0, 0}, {0, 1, 0}, {0, 0, 0}}’ from ‘<brace-enclosed initializer list>’ to ‘ImageProcessing::Kernel<int, 3ul, 3ul>’
ImageProcessing::Kernel<int,3,3> k = {{0,0,0},{0,1,0},{0,0,0}};
Edit: Test Code
You have a missing set of braces (the data member is a single array) and you need to make the data member public, because an aggregate cannot have private or protected members.
This is a simplified, working example:
#include <cstddef> // for std::size_t
template<typename T, std::size_t N, std::size_t M>
class Kernel {
public:
T kernelMatrix[N][M];
};
int main(){
Kernel<int,3,3> k = { {{0,0,0}, {0,1,0}, {0,0,0}} };
}

Initializing std::tuple from initializer list

I'm wondering whether the tuple can be initialized by initializer list (to be more precise - by initializer_list of initializer_lists)? Considering the tuple definition:
typedef std::tuple< std::array<short, 3>,
std::array<float, 2>,
std::array<unsigned char, 4>,
std::array<unsigned char, 4> > vertex;
is there any way of doing the following:
static vertex const nullvertex = { {{0, 0, 0}},
{{0.0, 0.0}},
{{0, 0, 0, 0}},
{{0, 0, 0, 0}} };
I just want to achieve same functionality I got using struct instead of tuple (thus only arrays are initialized by initializer_list):
static struct vertex {
std::array<short, 3> m_vertex_coords;
std::array<float, 2> m_texture_coords;
std::array<unsigned char, 4> m_color_1;
std::array<unsigned char, 4> m_color_2;
} const nullvertex = {
{{0, 0, 0}},
{{0.0, 0.0}},
{{0, 0, 0, 0}},
{{0, 0, 0, 0}}
};
There is no reason I must use tuples, just wondering. I'm asking, because I'm unable to go through g++ templates errors which are generated by my attempt of such tuple initialization.
#Motti: So I missed the proper syntax for uniform initialization -
static vertex const nullvertex = vertex{ {{0, 0, 0}},
{{0.0, 0.0}},
{{0, 0, 0, 0}},
{{0, 0, 0, 0}} };
and
static vertex const nullvertex{ {{0, 0, 0}},
{{0.0, 0.0}},
{{0, 0, 0, 0}},
{{0, 0, 0, 0}} };
But it seems that all the trouble lies in arrays, which got no constructor for initializer_list and wrapping arrays with proper constructor seems not so easy task.
Initializer lists aren't relevant for tuples.
I think that you're confusing two different uses of curly braces in C++0x.
initializer_list<T> is a homogeneous collection (all members must be of the same type, so not relevant for std::tuple)
Uniform initialization is where curly brackets are used in order to construct all kinds of objects; arrays, PODs and classes with constructors. Which also has the benefit of solving the most vexing parse)
Here's a simplified version:
std::tuple<int, char> t = { 1, '1' };
// error: converting to 'std::tuple<int, char>' from initializer list would use
// explicit constructor 'std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&)
// [with _U1 = int, _U2 = char, _T1 = int, _T2 = char]'
std::tuple<int, char> t { 1, '1' }; // note no assignment
// OK, but not an initializer list, uniform initialization
The error message says is that you're trying to implicitly call the constructor but it's an explicit constructor so you can't.
Basically what you're trying to do is something like this:
struct A {
explicit A(int) {}
};
A a0 = 3;
// Error: conversion from 'int' to non-scalar type 'A' requested
A a1 = {3};
// Error: converting to 'const A' from initializer list would use
// explicit constructor 'A::A(int)'
A a2(3); // OK C++98 style
A a3{3}; // OK C++0x Uniform initialization