How to use a numerical array literal - c++

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)
{
}

Related

When define an array, what is the diffrence on performance between define in main function and callee function? [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 1 year ago.
Consider:
[1]
int *func(){
int a[10];
//...
return a;
}
int main(){
int* a = func();
}
//在函数里开数组后往main函数回传指针
[2]
void func(int a*){
//...
}
int main(){
int a[10];
func(a);
}
//在main函数开个数组后传实参到函数里
Two programs can define an array a and use it. Which one is better? Why?在内存分配和性能上有啥区别?更推荐哪种方式?
Two codes can define an array a and use it.Which one is better? Why?
The second is better because the first is plain broken. You return a pointer to an array that will no longer exist once the function returns. In other words a dangling pointer.
Neither is what I would do in C++
I would use one of those constructs:
#include <array>
void function(int values[10])
{
}
template<std::size_t N>
void function_template(int(&values)[N])
{
}
template<std::size_t N>
void function_const_ref(const std::array<int, N>& arr) // pass by const reference if you only want to use values
{
}
template<std::size_t N>
void function_ref(std::array<int, N>& arr)
{
arr[1] = 42;
}
int main()
{
int arr[10]{}; // {} also initializes all values to 0!
function(arr);
function_template(arr); // keeps working even if you change size from 10 to something else
// or use std::array and you ca
std::array<int, 10> arr2{};
function_ref(arr2);
// this is I think the most C++ way
function_const_ref(arr2);
return 0;
}

use std:array as an argument of function

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

Can I use logical operators with function paramenters?

I want to create a function, where you can either use an int or a string variable as an parameter, but I don't know how.
I am writing a little example of what I want to achieve:
#include <iostream>
#include <string>
using namespace std;
int function((int a) || (string a))
{
...;
}
int main()
{
int intvar;
string stringvar;
function(intvar);
function(stringvar);
return 0;
}
Can I use logical operators with function paramenters?
No, you can't.
What you basically want is a function template or overload. The latter is the simplest way:
int function(int a)
{
// ...;
}
int function(string a)
{
// ...;
}
In case you have the same code for the varying types use a template:
template<typename T>
int function(T a)
{
static_assert(std::is_convertible<T,int>() || std::is_convertible<T,std::string>());
// ...;
}
You probably want to overload the function and call one from the other, something like:
int function(int a) {
// handle int parameter
}
int function(const string& s) {
int a = stoi(s);
return function(a);
}

Extract elements from a vector of object

Given a vector of objects, is there an elegant way to extract its member? I am currently just using a for loop but it would be nice if there is a way to do it. Example:
#include <vector>
struct Object {
int x;
float y;
};
int main() {
std::vector<Object> obj;
// Fill up obj
std::vector<int> all_x = obj.x; // Won't work obviously
}
With range-v3, it would simply be
std::vector<int> xs = objs | ranges::view::transform(&Object::x);
or just use the view:
auto xs = objs | ranges::view::transform(&Object::x);
Demo
As std::vector (or c++ in general) does not support covariant aggregation, there is no syntactically pretty way to do what you want.
If you really want to initialize all_x with x members of obj elements, then you can define a new iterator class, like that:
class getx_iter : public vector<Object>::iterator
{
public:
getx_iter(const vector<Object>::iterator &iter) : vector<Object>::iterator(iter) {}
int operator*() { return (*this)->x; }
};
Working code example
If you're okay with initializing an empty vector and then filling it, std::transform with a labmda is a clearer option (as #andars suggested).
You could also avoid extra initialization by using vector::reserve() and back_inserter:
xs.reserve(foos.size());
std::transform(foos.begin(), foos.end(), back_inserter(xs), [](Foo f){return f.x;});
Also notice that while x is a private member of Object and has no getters, it will be quite hard to extract it.
I can't think of a really good way.
One alternative would be to use std::transform with a lambda.
#include <vector>
#include <algorithm>
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
int main() {
std::vector<Foo> foos;
for (int i = 0; i<10; i++) {
foos.push_back(Foo(i));
}
std::vector<int> xs;
xs.resize(foos.size());
std::transform(foos.begin(), foos.end(), xs.begin(), [](Foo f){return f.x;});
}
Some template and macro magic, and it works:
#include <vector>
#include <algorithm>
using namespace std;
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
#define GETFIELD(type, field) [](const type & obj){return obj.field;}
template<typename T,typename U, typename TMapper>
void MapVector(vector<T>& src, vector<U>& dst, TMapper mapper) {
for (const auto& it: src) {
dst.push_back(mapper(it));
}
}
#define MapVectorField(src, dst, field) MapVector(src, dst, GETFIELD(decltype(src)::value_type, field))
int main() {
vector<Foo> vFoo;
for (int i = 0; i < 10; i++) {
vFoo.push_back(Foo(i));
}
vector<int> vX;
MapVector(vFoo, vX, GETFIELD(Foo, x));
MapVectorField(vFoo, vX, x);
for (int i = 0; i < vX.size(); i++) {
printf("%d\n", vX[i]);
}
}
Of course, remember that it is not very good to name macro MapVectorField as it is function, or write using namespace std in production.
Here's another macro that's pretty easy to use. It does require the programmer to know that the internal loop variable name is "e", for element. If you keep that in mind, it will work for both fields or methods, and also for normal objects or pointers to objects.
The macro is simply:
#define map(vTarget, vSource, eField) \
for (auto e: vSource) { vTarget.push_back(eField); }
For example, suppose we have a class named Person which has a string name field and an int age field, and we want to extract just the names into a new vector. An example usage might then be:
map(names, people, e.name);
Note the "e" in the third parameter. This is required because the macro uses the variable "e" to iterator over the elements in the vector. So keep in mind which syntax you need to use. I believe these are the 4 cases:
e.field
e.method()
e->field
e->method()
Let's try them out. Here's a full example. Hey, if anyone has a more elegant join solution, I'm all ears.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define map(vTarget, vSource, eField) \
for (auto e: vSource) { vTarget.push_back(eField); }
class Person {
public:
string name;
int age;
public:
Person(string name, int age) {
this->name=name;
this->age=age;
}
string& getName() {return name;}
int getAge() {return age;}
};
string join(vector<string> vSource, const string separator) {
string buf;
bool first=true;
for (string e: vSource) {
if (first) {
first=false;
} else {
buf+=separator;
}
buf+=e;
}
return buf;
}
int main(int argc, char **argv) {
// using a normal Object
vector<Person> people;
vector<string> names;
people.push_back(Person("john", 27));
people.push_back(Person("jane", 26));
names.clear();
map(names, people, e.name);
cout << join(names, ",") << endl;
names.clear();
map(names, people, e.getName());
cout << join(names, ",") << endl;
// using a pointer to an object
vector<Person*> morePeople;
morePeople.push_back(new Person("bob", 27));
morePeople.push_back(new Person("amy", 26));
names.clear();
map(names, morePeople, e->name);
cout << join(names, ",") << endl;
names.clear();
map(names, morePeople, e->getName());
cout << join(names, ",") << endl;
}
Sample output:
john,jane
john,jane
bob,amy
bob,amy

How to pass two parameters when using std::mem_fun?

Lets say I have hierarchy like this (This is just a test program. Please do not point anything related to memory leaks, destructor is not virtual etc):
class I
{
public:
virtual void fun(int n, int n1) = 0;
};
class A : public I
{
public:
void fun(int n, int n1)
{
std::cout<<"A::fun():" <<n<<" and n1:" <<n1<<"\n";
}
};
class B : public I
{
public:
void fun(int n, int n1)
{
std::cout<<"B::fun():" <<n<<" and n1:" <<n1<<"\n";
}
};
int main()
{
std::vector<I*> a;
a.push_back(new A);
a.push_back(new B);
//I want to use std::for_each to call function fun with two arguments.
}
How do I call fun() method which takes two arguments using the std::for_each ? I think I have to use std::mem_fun probably with std::bind2nd but am not able to figure out how to do this. Any clue how to achieve this? I am not using boost.
You could create your own functor like this:
class Apply
{
private:
int arg1, arg2;
public:
Apply(int n, int n1)
: arg1(n), arg2(n1)
{}
void operator() (I* pI) const
{
pI->fun(arg1, arg2);
}
};
int main ()
{
// ...
std::for_each(a.begin(), a.end(), Apply(n, n1));
}
or use boost::bind like this:
std::for_each(
a.begin(),
a.end(),
boost::bind(&I::fun, _1, n, n1));
You can't do this with the std binders. You can of course write your own functor.
struct TwoArguments
{
int one;
int two;
TwoArguments( int one, int two ) : one(one),two(two){
}
void operator()( I* i ) const {
i->fun( one, two );
}
};
Another way to do this would be to use templates. (Please tell me if it's a bad practice though!)
template<int N, int N1>
void Apply(I* i)
{
i->fun(N, N1);
}
std::for_each(a.begin(), a.end(), Apply<firstParam, secondParam>);
That would be good if you don't intend to call it with a lot of different parameters since it would generate code for every combination you made.