use std:array as an argument of function - c++

I have seen here :http://www.cplusplus.com/doc/tutorial/arrays/
that
int[N] is the same as std::array<int,N> in C++.
I would like to use this notation in order to avoid to pass N as an argument of a function.
I would like to do something like that
returnedType function(array tab)
instead of
returnedType function(int tab, int N)
but i can't make the type array because i must write array<int,N> and i don't know N in advance.
Has Somebody a solution?

Make the function a function template, like so:
template <size_t N>
void function(std::array<int, N> arr)
{
// do something with arr
}
and call it like:
int main()
{
std::array<int, 3> a;
function(a);
std::array<int, 15> b;
function(b);
}

if you do not know the size in advance, std::vector is what you want
//function taking vector:
int MyFunc(const std::vector<int>& vec)
{
//.. do stuff
return 5;
}
std::vector<int> myvec;
//add somme entries:
myvec.push_back(1);
myvec.push_back(2);
myvec.push_back(3);
//call function:
int res = MyFunc(myvec);

Related

Convert int array to std::vector<int*>

I'm trying to "convert" an integer C style array to std::vector<int*> without using a for loop, or rather insert pointers of all array items in a vector.
I'm currently implementing this by doing the follow:
for (size_t i = 0; i < 5; i++)
{
vector.push_back(&values[i]);
}
Is it possible to implement this by using std::vector::insert() and std::being/end?
std::transform is a useful algorithm in <algorithm> for copying values between containers that aren't implicitly compatible but for which you can provide a transformation function.
Here is an example of how you could populate a std::vector<int*> from a std::array<int, N>
int values[5] = { 1,2,3,4,5 };
std::vector<int*> v1;
std::transform(
std::begin(values), std::end(values), // Copy from
std::back_inserter(v1), // Copy to
[](auto& i) { // Transformation function
return &i;
});
Edit : Changed std::array<int, 5> to int[5] to account for edits in the question.
The code below is rather fancy way to do what you want, but it is generic and it doesn't use for loop - it just passes pointers of array's elements to vector constructor:
template<class T, size_t ... Ints, size_t N>
std::vector<T*> makePtrsHelper(std::array<T,N>& arr, std::index_sequence<Ints...>) {
return std::vector<T*>{ & std::get<Ints>(arr)... };
// vector ctor taking pointers to array's elements
}
template<class T, size_t N>
std::vector<T*> makePtrs(std::array<T,N>& array) {
return makePtrsHelper(array, std::make_index_sequence<N>{});
}
int main(){
std::array<int,5> ar{1,2,3,4,5};
std::vector<int*> v = makePtrs(ar);
Live demo
Note: as pointed out in comments my below answer is wrongly related to vector<int> not vector<int*> which was asked for in question.
Solution with std::copy and C-style array:
int ar[] = {1,2,3,4,3,2,1};
std::vector<int> vec;
std::copy(ar, ar+sizeof(ar)/sizeof(ar[0]), back_inserter(vec));

How to pass a 2D vector to a function using pass-by-reference C++

struct st
{
int to, cost;
};
void fun(vector<st>&v1[10])
{
vector<st>v2[10];
v1=v2;
}
int main()
{
vector<st>arr[10];
fun(arr);
}
I want to pass a 2D vector in a function by reference and swap the vector with another vector in that function. But I am getting error. I don't want to do it with pair vector. I want to use structure here. How to do it?
here is a screenshot of my error messege
One major problem: When passing an array as an argument, what is really passed is a pointer.
It can easily be solved by using std::array instead:
void fun(std::array<std::vector<st>, 10>& v1)
{
std::array<std::vector<st>, 10> v2;
// Initialize v2...
v1 = v2;
}
int main()
{
std::array<std::vector<st>, 10> arr;
fun(arr);
}
After introducing std::arrayabove, I would rather recommend returning the array instead of passing by reference:
std::array<std::vector<st>, 10> fun()
{
std::array<std::vector<st>, 10> v2;
// Initialize v2...
return v2;
}
int main()
{
std::array<std::vector<st>, 10> arr = fun();
}

How to use a numerical array literal

I would like to use an array for one time only, and would like to not having to declare a name for it, e.g, something like
int a,b,c;
void foo(int[],int);
...
a=1; b=2; c=3;
foo({a,b,c},3);
...
I am pretty sure this is not going to work, but how can I make it work?
If you use std::vector or std::array, things become easier.
void foo(std::vector<int> xs)
{
for (const auto& x : xs)
{
std::cout << x << ' ';
}
}
int main()
{
foo({ 10,11,12 });
}
If you want to use an array "literal" only once, consider an rvalue reference to std::array:
// Declaration:
template<size_t s>
void foo(std::array<int, s>&& arr) {
// ....
}
//Call:
foo(std::array<int, 3>{1,2,3});
Using std::vector or std::array as in Nicky C's answer is better.
But to answer your question as is, you may do:
void foo(int[],int);
int main()
{
foo(std::vector<int>{10, 11, 12}.data(), 3);
}
Another way not mentioned yet is to use a std::initializer_list.
#include <initializer_list>
void foo(std::initializer_list<int> lst,int i)
{
}
int main()
{
int a,b,c;
a=1; b=2; c=3;
foo({a,b,c},3);
}
or you could use a template.
template<typename T, std::size_t N>
void foo(const T (&lst)[N],int i)
{
}

Alternate between different data-types

I'm trying to figure this out, and, it's really annoying me. I have a function that converts either an array or a vector into a vector of complex numbers, but, I do not know how it would be possible for the function to be able to accept both double arrays, as well as double vectors. I've tried using templates, but, this does not seem to work.template
template<typename T>
vector<Complex::complex> convertToComplex(T &vals)
{
}
Value::Value(vector<double> &vals, int N) {
};
Value::Value(double *vals, int N) {
};
What I am hoping for is this:
int main()
{
double[] vals = {1, 2, 3, 4, 5};
int foo = 4;
Value v(vals, foo); // this would work and pass the array to the constructor, which would
// then pass the values to the function and covert this to a
// vector<complex>
}
I could do the same for a vector as well.. I don't know whether or not templates are the right approach for this.
You could make your function and constructor a template that takes two iterators:
template<typename Iterator>
vector<Complex::complex> convertToComplex(Iterator begin, Iterator end)
{
}
class Value
{
public:
template <Iteraror>
Value(Iterator begin, Iterator end)
{
vector<Complex::complex> vec = comvertToComplex(begin, end);
}
....
};
then
double[] vals = {1, 2, 3, 4, 5};
Value v(std::begin(vals), std::end(vals));
std::vector<double> vec{1,2,3,4,5,6,7};
Value v2(v.begin(), v.end());
I have omitted foo because it isn't very clear to me what its role is.
No need to define a template function here if you only want to support doubles.
You should do it like this, it's much simpler:
vector<Complex::complex> convertToComplex(const double* array, size_t len)
{
// ... your implementation
}
vector<Complex::complex> convertToComplex(const vector<double>& v, size_t len)
{
return convertToComplex(v.data(), len);
}
That's it!

C++ : Array of struct as function parameter

I have a struct:
typedef struct
{
int nNum;
string str;
}KeyPair;
Let's say I initialize my struct:
KeyPair keys[] =
{ {0, "tester"},
{2, "yadah"},
{0, "tester"}
};
I want to use the initialized values in a function. How do I pass this array struct as a function parameter?
I have:
FetchKeys( KeyPair *pKeys)
{
//get the contents of keys[] here...
}
How about?
template<int N> void FetchKeys(KeyPair const (&r)[N]){}
EDIT 2:
Or even
template<int N> void FetchKeys(KeyPair const (*p)[N])
with the call as
FetchKeys(&keys);
You can do it as #MSalters mentioned, or you can create a std::vector<KeyPair> and pass it to the function. Here is a sample code:
using namespace std;
struct KeyPair
{
int nNum;
string str;
};
void fetchKeys(const vector<KeyPair>& keys)
{
//Go through elements of the vector
vector<KeyPair>::const_iterator iter = keys.begin();
for(; iter != keys.end(); ++iter)
{
const KeyPair& pair = *iter;
}
}
int main()
{
KeyPair keys[] = {{0, "tester"},
{2, "yadah"},
{0, "tester"}
};
//Create a vector out of the array you are having
vector<KeyPair> v(keys, keys + sizeof(keys)/sizeof(keys[0]));
//Pass this vector to the function. This is safe as vector knows
//how many element it contains
fetchKeys(v);
return 0;
}
Should be
// Definition
void FetchKeys( KeyPair *pKeys, int nKeys)
{
//get the contents of keys[] here...
}
// Call
FetchKeys(keys, sizeof(keys)/sizeof(keys[0]));
In c/c++ the name of the array (of any type) represents the address of the first element of the array, so
keys and &keys [0] are same.
You can pass any one of them for KeyPair*.
You just callFetchKeys(keys);
EDIT
Pay attention to declare FetchKeys' return type.
EDIT 2
If you also need the number of items, you add size as FetchKeys input parameters:
void FetchKeys(KeyPair*, size_t size);
and call FetchKeys(keys, sizeof(keys)/sizeof(*keys));
BTW, state all your question by editing your first post if you can.
Depending on what you want to do you can even use boost range and pass it to function as a pair of iterators:
void FetchKeys(KeyPair *begin, KeyPair *end)
FetchKeys(boost::begin(keys), boost::end(keys));
See this answer: How can I pass an array by reference to a function in C++?
Wrap it in a structure, nice and easy..
#include <iostream>
struct foo
{
int a;
int b;
};
template <typename _T, size_t _size>
struct array_of
{
static size_t size() { return _size; }
_T data[_size];
};
template <typename _at>
void test(_at & array)
{
cout << "size: " << _at::size() << std::endl;
}
int main(void)
{
array_of<foo, 3> a = {{ {1,2}, {2,2}, {3,2} }};
test(a);
}
EDIT: URGH, I can't see the toolbar to format the code correctly, hopefully the tags works..
i use VS 2008, and this works fine for me.
#include "stdafx.h"
typedef struct
{
int nNum;
CString str;
}KeyPair;
void FetchKeys( KeyPair *pKeys);
int _tmain(int argc, _TCHAR* argv[])
{
KeyPair keys[] =
{ {0, _T("tester")},
{2, _T("yadah")},
{0, _T("tester")}
};
FetchKeys(keys); //--> just pass the initialized variable.
return 0;
}
void FetchKeys(KeyPair *pKeys)
{
printf("%d, %s\n",pKeys[0].nNum, pKeys[0].str);
}
I don't understand the difficulty. correct me if i'm wrong. To keep it simple, i avoided using vectors, templates and etc.
edit: to know size of struct, you can pass one more arg.