Initializing struct vector with brace-enclosed initializer list - c++

I initialize normal-type vectors like this:
vector<float> data = {0.0f, 0.0f};
But when I use structure instead of normal-type
struct Vertex
{
float position[3];
float color[4];
};
vector<Vertex> data = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}};
I get error could not convert '{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}' from '<brace-enclosed initializer list>' to 'std::vector<Vertex>'. What's wrong with this?

A set of {} is missing:
std::vector<Vertex> data =
{ // for the vector
{ // for a Vertex
{0.0f, 0.0f, 0.0f}, // for array 'position'
{0.0f, 0.0f, 0.0f, 0.0f} // for array 'color'
},
{
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 0.0f}
}
};

you need one more {} actually
vector<Vertex> data = {{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}};
one '{' for vector, one for struct, one (couple of) for struct member-arrays...

An object with vector members can also be initialized.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Test
{
public:
struct NumStr
{
int num;
string str;
};
Test(vector<int> v1,vector<NumStr> v2) : _v1(v1),_v2(v2) {}
vector<int> _v1;
vector<NumStr> _v2;
};
int main()
{
Test t={ {1,2,3}, {{1,"one"}, {2,"two"}, {3,"three"}} };
cout << t._v1[1] << " " << t._v2[1].num << " " << t._v2[1].str << endl;
return 0;
}
2 2 two

Related

How to write vectors member to file

I'm trying to write vector's members to file but I get this error for loop operation:
no operator "<<" matches these operands
How can I write those members to file?
std::ofstream raport;
raport.open("test.txt", std::ios_base::app);
std::vector<std::vector<float>> targetInputs = {
{0.0f, 0.0f},
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 1.0f}
};
for (int i = 0;i < targetInputs.size(); i++) {
raport << targetInputs[i];
}
Example with range based for loop.
The const references are there since output should never modify the input data.
The ostringstream is a standin stream for your file.
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ostringstream raport;
//raport.open("test.txt", std::ios_base::app);
std::vector<std::vector<float>> targetInputs = {
{0.0f, 0.0f},
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 1.0f}
};
for (const auto& values : targetInputs)
{
for (const auto& value : values)
{
raport << value << " ";
}
raport << "\n";
}
std::cout << raport.str();
return 0;
}

C++: How to pass array into an instance of a class and get the sizeof() it?

I want to pass an array into an instance of a class to be used within it. However, I can't get sizeof() the array. I get the warning "Sizeof on array function parameter will return size of 'float *' instead of 'float []'. "
int main() {
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
{
Class I want to pass array to
class Store{
float array[];
public:
Store(float temp[]){
std::cout<<"\n"<<sizeof(temp); //can't get sizeof
for(int i=0;i<9;i++){
array[i]=temp[i];
};
}
void showArrayContents(){
for(int i=0;i<9;i++){
std::cout<<array[i];
}
}
};
How can I fix to get sizeof() correctly?
EDIT: I'm not trying to find how many elements are in the array but the amount of memory it takes up, which should be 40 bytes.
I want to pass an array into an instance of a class to be used within it.
Ok, there are several ways to do that, I'll show you some of those later.
However, I can't get sizeof() the array.
You can't get it inside the function, after the array decayed to a pointer.
Store(float temp[]){
// ^^^^^^ This is a pointer to float, not an array
}
Other than explicitly passing the size as a function argument, you could pass a reference to an array, using a template parameter to store the size (1).
#include <vector>
#include <iostream>
class Store
{
std::vector<float> values_;
public:
template< std::size_t N >
Store(float const (&temp)[N]) : values_{temp, temp + N}
{}// ^^^^^^^^^^
void showArrayContents() const noexcept
{
for(auto i : values_)
{
std::cout << ' ' << i;
}
std::cout << '\n';
}
};
int main()
{
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
}
Get rid of the source array and use a std::initializer_list (2).
#include <vector>
#include <iostream>
#include <initializer_list>
class Store
{
std::vector<float> values_;
public:
Store(std::initializer_list<float> src) : values_{src}
{}
//...
};
int main()
{
Store test{1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
test.showArrayContents();
}
If the size never has to change during the lifetime of Store, you can use a std::array (3).
#include <algorithm>
#include <array>
#include <iostream>
template< class T, std::size_t N >
class Store
{
std::array<T, N> values_;
public:
Store(T const (&src)[N])
{
std::copy(src, src + N, values_.begin());
}
//...
};
//deduction guide
template<class T, std::size_t N> Store( T (&src)[N] ) -> Store<T, N>;
int main()
{
float info[]={1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
Store test(info);
test.showArrayContents();
}
You can also avoid the source array and initialize the class with a constructor accepting a template parameter pack (4).
#include <algorithm>
#include <array>
#include <iostream>
#include <type_traits>
template< class T, std::size_t N >
class Store
{
std::array<T, N> values_;
public:
template< class... Args >
Store(Args... args) : values_{args...}
{}
//...
};
//deduction guide
template< class... Args >
Store(Args &&... ) -> Store<std::common_type_t<Args...>, sizeof...(Args)>;
int main()
{
Store test{1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
test.showArrayContents();
}
For a static C-style array it is possible to infer its size using the expression
sizeof(info) / sizeof(*info)
This is also commonly implemented via a macro ARRAY_SIZE. Beware however that in the above code there is no check that the actual array is a static one.
Conversely, for a dynamically allocated C-style array, there is no possibility to infer its size, since the variable itself is nothing but a pointer.
In the class constructor, even if you knew the size of the array (for instance by passing the size as parameter), or if you assume that only a static array is used (and you employ the code above to infer its size), your code has a serious bug here:
for(int i=0;i<9;i++){
array[i]=temp[i];
};
You are copying the elements of temp into array, but did you reserve memory for that? Again, array is merely a pointer to float, and if you do not explicitly allocate memory, in the above code you are writing into a part of memory which does not pertain to array. Hence you have UB.
If you know at compile time the size of the array, the right type to use is std::array.
For instance
std::array<float, 10> info = {1.0f,2.3f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,67.8f};
And then you can pass it to the class with something like
class Store{
std::array<float, 10> array;
public:
Store(std::array<float, 10> temp) : array{temp} { }
...
With a std::array you can always know its size with std::array::size.
How can I fix to get sizeof() correctly?
Option #1: you could pass in the size of the array.
#include <array>
#include <cstddef>
#include <iostream>
using std::cout;
using std::size;
using std::size_t;
namespace {
class Store {
size_t array_size;
float* array;
public:
~Store() {
delete[] array;
}
Store(float temp[], size_t temp_size) : array_size{temp_size} {
cout << "temp_size:" << temp_size << "\n";
array = new float[temp_size];
for (size_t i = 0; i < temp_size; ++i) {
array[i] = temp[i];
}
}
Store(Store const&) = delete;
auto operator=(Store const&) -> Store& = delete;
void showArrayContents() {
auto sep = "";
for (size_t i = 0; i < array_size; ++i) {
cout << sep << array[i];
sep = " ";
}
cout << "\n";
}
};
} // anon
int main() {
float info[] = { 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
Store test(info, size(info));
test.showArrayContents();
}
Option #2: you could use a template constructor for the array.
#include <cstddef>
#include <iostream>
using std::cout;
using std::size_t;
namespace {
class Store {
size_t array_size;
float* array;
public:
~Store() {
delete[] array;
}
template <size_t N>
Store(float (&temp)[N]) : array_size{N} {
cout << "N:" << N << "\n";
array = new float[N];
for (size_t i = 0; i < N; ++i) {
array[i] = temp[i];
}
}
Store(Store const&) = delete;
auto operator=(Store const&) -> Store& = delete;
void showArrayContents() {
auto sep = "";
for (size_t i = 0; i < array_size; ++i) {
cout << sep << array[i];
sep = " ";
}
cout << "\n";
}
};
} // anon
int main() {
float info[] = { 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
Store test(info);
test.showArrayContents();
}
Option #3 (best option): you could use std::vector.
#include <cstddef>
#include <iostream>
#include <vector>
#include <utility>
using std::cout;
using std::move;
using std::ostream;
using std::size_t;
using std::vector;
namespace {
class Store {
vector<float> array;
public:
Store(vector<float> temp) : array{move(temp)} {
cout << "temp size:" << temp.size() << "\n";
}
void showArrayContents(ostream& out) const {
auto sep = "";
for (auto&& e : array) {
out << sep << e;
sep = " ";
}
out << "\n";
}
};
} // anon
int main() {
auto info = vector<float>{ 1.0f, 2.3f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 67.8f };
auto test = Store{info};
test.showArrayContents(cout);
}
You should pass the array length as an argument also, when you pass an array to function what you actually pass is a pointer to start location of array i.e. float* in your case, so when you ask for size it simply gives you size of pointer .
So either pass the size explicitly, or use std::vector which will give you the length.
other than that if class Store is the owner of array, why not define it inside class?

Find dirac in wave file

This is about room correction.
I have a reference wave file, which is played back via a stereo amplifier and recorded using a microphone (umik 1).
Now my problem is that I have to manually find the diracs (loud „clicks“) inserted into the reference audio, and manually calculate the clock drift of the microphone. For example, in the reference file the click is at 0.5s and another one at 62s.
In the file recorded the clicks are slightly off. I‘m currently checking the wave file and calculate the actual clock / sample rate from the actual recorded distance between the two clicks.
How can I recognize this click in code, and get required info to do the calculations?
You can:
go forward in the audio signal and find the first sample whose absolute value is above the noise_level threshold
then, walk back from that location to find the first zero-crossing.
find_relevant_start implements this, and you can use it like so:
// You may need to adjust `noise_level` based on the characteristics of your audio.
constexpr auto noise_level = 0.1f;
std::vector<float> audio;
auto it = find_relevant_start(audio.begin(), audio.end(), noise_level);
if(it==audio.end()) {
// not found, maybe 'noise_level' was too high?
}
This is the code (from a personal project):
/*
* #param abs_relevant_level : if the absolute value of the signal
* is bigger than this value, it is considered to be relevant.
* Use a non-zero value if your signal contains noise.
*/
template<typename ITER, typename VAL = typename ITER::value_type>
ITER first_relevant_value(ITER it, ITER end, VAL abs_relevant_level) {
for(; it != end; ++ it ) {
if(std::abs(*it) > abs_relevant_level) {
break;
}
}
return it;
}
template<typename ITER>
ITER first_zero_crossing(ITER it, ITER end) {
using VAL = typename ITER::value_type;
using Tr = NumTraits<VAL>;
bool first = true;
VAL prev;
while(it != end) {
auto cur = *it;
if(cur == Tr::zero()) {
break;
}
if(first) {
first = false;
}
else if(prev * cur < Tr::zero()) {
break;
}
prev = cur;
++it;
}
return it;
}
template<typename ITER, typename VAL = typename ITER::value_type>
ITER find_relevant_start(ITER it, ITER end, VAL abs_relevant_level) {
auto it_relevant_value = first_relevant_value(it, end, abs_relevant_level);
if(it_relevant_value == end) {
return end;
}
using REVERSE_ITER = std::reverse_iterator<ITER>;
auto rit = REVERSE_ITER(it_relevant_value + 1);
auto rend = REVERSE_ITER(it);
auto rzero = first_zero_crossing( rit, rend);
// first_zero_crossing returns the iterator after the zero crossing (in the reverse direction)
// so rzero.base() is the iterator on the other side of the zero crossing
return rzero.base();
}
These unit tests will show you how it performs on simple arrays:
TEST(Peaks, find_relevant_start)
{
using namespace imajuscule;
{
std::vector<float> v{ -0.04f, -0.03f, -0.02f, -0.01f, 0.1f, 0.2f, 0.3f };
auto it = find_relevant_start(v.begin(), v.end(), 0.15f);
ASSERT_EQ(0.1f, *it);
}
{
std::vector<float> v{ -0.04f, -0.03f, -0.02f, -0.01f, 0.1f, 0.2f, 0.3f };
auto it = find_relevant_start(v.begin(), v.end(), 0.25f);
// the algorithm finds the first relevant value, and goes backward from there to find the first sign change and returns the sample just after
ASSERT_EQ(0.1f, *it);
}
{
std::vector<float> v{ 0.04f, 0.03f, 0.02f, 0.01f, -0.1f, -0.2f, -0.3f };
auto it = find_relevant_start(v.begin(), v.end(), 0.25f);
// the algorithm finds the first relevant value, and goes backward from there to find the first sign change and returns the sample just after
ASSERT_EQ(-0.1f, *it);
}
{
std::vector<float> v{ -0.04f, -0.03f, -0.02f, -0.01f, 0.1f, 0.2f, 0.3f };
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
// the level is too high and was never reached so "end" should be returned
ASSERT_EQ(v.end(), it);
}
{
std::vector<float> v{ 1.f, 2.f, 1.f };
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(v.begin(), it);
}
{
std::vector<float> v{ -1.f, -2.f, -1.f };
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(v.begin(), it);
}
{
std::vector<float> v;
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(v.end(), it);
}
{
std::vector<float> v{.1f};
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(v.end(), it);
}
{
std::vector<float> v{1.f};
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(1.f, *it);
}
{
std::vector<float> v{-1.f};
auto it = find_relevant_start(v.begin(), v.end(), 0.5f);
ASSERT_EQ(-1.f, *it);
}
}

Parameters passed by value displayed incorrectly in the visual studio 2015 x64 debugger?

x86 works fine.
x86 debug values screenshot
But x64 display incorrectly.
x64 debug values screenshot
Here is the code.
struct vector3 { float x, y, z; };
vector3 mul(vector3 v1, vector3 v2)
{
vector3 v3 = { v1.x * v2.x, v1.y * v2.y, v1.z * v2.z };
return v3;
}
int main()
{
vector3 a = { 1.0f, 1.0f, 1.0f };
vector3 b = { 2.0f, 2.0f, 2.0f };
vector3 c = mul(a, b);
return 0;
}
I first noticed this in one of my personal projects and was able to replicate it in a new project (images above are from new project).
I'm wonder what is causing it.
Maybe a bad install, or a VS bug?
Is it able to be replicated on other machines?
This is as simple as I can make the code.
Note this code works fine on x64:
struct vector2 { float x, y; };
vector2 mul(vector2 v1, vector2 v2)
{
vector2 v3 = { v1.x * v2.x, v1.y * v2.y };
return v3;
}
int main()
{
vector2 a = { 1.0f, 1.0f };
vector2 b = { 2.0f, 2.0f };
vector2 c = mul(a, b);
return 0;
}
Reinstalling Visual studio fixed the problem.

operator overload deletes function

So I am getting back into graphics programming, and the book I'm using for reference (Frank Luna's 3D Game Programming with DirectX 11), uses no-longer-supported xnamath.h. I have changed it to use DirectXMath.h seemingly without any problems. However, there seems to be problem when I overload the ostream << operator to work with XMVECTORs. When I try to use cout to print an XMVECTOR object, I get this error:
Error 1 error C2280: 'std::basic_ostream<char,std::char_traits<char>>::basic_ostream(const std::basic_ostream<char,std::char_traits<char>> &)' : attempting to reference a deleted function
There is only one file in this program (main.cpp):
#include <Windows.h>
#include <DirectXMath.h>
#include <iostream>
using namespace DirectX;
using namespace std;
// Overload the "<<" operators so that we can use cout to output XMVECTOR objects
ostream& operator<<(ostream os, FXMVECTOR v);
int main() {
cout.setf(ios_base::boolalpha);
// Check support for SSE2 (Pentium4, AMD K8, and above
if (!XMVerifyCPUSupport()) {
cout << "DirectX Math not supported" << endl;
return 0;
}
XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);
XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);
// Vector addition: XMVECTOR operator +
XMVECTOR a = u + v;
cout << a;
}
ostream& operator<<(ostream os, FXMVECTOR v) {
XMFLOAT3 dest;
XMStoreFloat3(&dest, v);
os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")";
return os;
}
I have a feeling I'm messing up the operator-overloading, but I'm not really sure at this point. I couldn't find any similar problems online, but I hope I'm just overlooking something really basic. Any advice will be appreciated.
The problem is in this line:
ostream& operator<<(ostream os, FXMVECTOR v) {
Change it to
ostream& operator<<(ostream& os, FXMVECTOR v) {
The first line tries to make a copy of ostream using a copy constructor. That is not allowed.