passing unnamed array to function

P

poorboywilly

I've been unable to find any information on this through any search
engines. Is there any way to pass an unnamed (temporary) array to a
function?
e.g.

void f0(const int ar[5]);
void f1(const int ar[]);


f0( {1, 2, 3, 4, 5} ); //does not compile
f1( {1, 2, 3} ); //does not compile

int n_set[] = {1, 2, 3, 4, 5};
f0(n_set); //these both compile (of course)
f1(n_set);

I know I can use an STL container instead and pass an unnamed STL
container, but an STL container doesn't allow me to set construct it
with, say, 5 arbitrary values.

So I guess my question is, why can I not initialize a function
argument with the array "shorthand" notation, and is there an
alternative syntax that will allow this?

thanks,
--Jason
 
V

Victor Bazarov

poorboywilly said:
I've been unable to find any information on this through any search
engines. Is there any way to pass an unnamed (temporary) array to a
function?

There are no "array literals" in C++ (beyond arrays of 'char const').

You can probably create a way. Here is what you need to do. Define
a class (better a template) which will have a constructor with '...'
for the argument. It will manage its own memory, say. A member of
that class will be the pointer to the dynamic memory, so you would
be able to use syntax like

f1(make_array(1,2,3,4).pointer);

It might look something like

template<class T> struct make_array_t {
T *pointer;
make_array_t(T t ...); // the constructor - allocates and
// fills the memory
~make_array_t();
private:
// those are prohibited
make_array_t& operator=(make_array_t const&);
make_array_t(make_array_t const&);
};

// and here is the factory:
template<class T> make_array_t<T> make_array(T t ...);

All you need to figure out is how you manage the variadic arguments
(how you stop processing the list, that is).

V
 
P

Puppet_Sock

I've been unable to find any information on this through any search
engines.  Is there any way to pass an unnamed (temporary) array to a
function?
e.g.

void f0(const int ar[5]);
void f1(const int ar[]);

f0( {1, 2, 3, 4, 5} );     //does not compile
f1( {1, 2, 3} );            //does not compile
[snip]

What are you trying to accomplish through this?
Possibly there's a better way to get it than by
doing this.
int n_set[] = {1, 2, 3, 4, 5};
f0(n_set); //these both compile (of course)
f1(n_set);

If you just put that in a scope, say with { }
around it, would that accomplish what you want?
Or by putting this stuff inside a function call.
Socks
 
J

Joe Greer

I've been unable to find any information on this through any search
engines. Is there any way to pass an unnamed (temporary) array to a
function?
e.g.

void f0(const int ar[5]);
void f1(const int ar[]);


f0( {1, 2, 3, 4, 5} ); //does not compile
f1( {1, 2, 3} ); //does not compile

int n_set[] = {1, 2, 3, 4, 5};
f0(n_set); //these both compile (of course)
f1(n_set);

I know I can use an STL container instead and pass an unnamed STL
container, but an STL container doesn't allow me to set construct it
with, say, 5 arbitrary values.

So I guess my question is, why can I not initialize a function
argument with the array "shorthand" notation, and is there an
alternative syntax that will allow this?

The short answer is because the C++ syntax doesn't allow it. The longer
answer is that in general, objects have to exist somewhere. In the case
of temporary objects, this is normally on the stack, though compilers
are allowed to put them anywhere. Thing is, after the temporary goes
out of scope, the memory is reclaimed. This doesn't leave a lot of
options for temporary arrays. Most of the languages which allow what
you wrote also have garbage collectors tightly integrated with the
language. This more easily allows temporaries to be put in the garbage
collected heap, because you don't have to worry about leaking the
allocated memory. This kind of tight integration with a garbage
collector will never be the case in C++.

You could look at the 'assign' library in boost. It lets you write
things like.

std::vector<int> v;
v += 1,2,3,4,5;

And a few other collection initializing tricks.

HTH,
joe
 
J

Joe Greer

You could look at the 'assign' library in boost. It lets you write
things like.

std::vector<int> v;
v += 1,2,3,4,5;

And a few other collection initializing tricks.

Actually, the boost assign library has a to_list() routine which allows for the
construction of temporary arrays (at least in some contexts).

joe
 
P

poorboywilly

engines. Is there any way to pass an unnamed (temporary) array to a
function?
e.g.
void f0(const int ar[5]);
void f1(const int ar[]);
f0( {1, 2, 3, 4, 5} ); //does not compile
f1( {1, 2, 3} ); //does not compile

[snip]

What are you trying to accomplish through this?
Possibly there's a better way to get it than by
doing this.

Specifically I want to pass an array to a template's constructor. The
number of array elements (lets call it n) I want to pass to this
constructor will be determined by a template parameter, so I know in
the constructor how many elements there should be in the array. On
one hand, if I wanted to do template (partial) specializations for
each conceivably useful value of n, I could simply create a
constructor of the form

constructor(int arg1, int arg2, ..., int argn) { ... }

for each specialization. Too much work. On the other hand, I can
avoid the template specializations by creating one constructor of the
form

constructor(const int args[]) { ... }

and, since I know n due to one of my template parameters, it is very
easy to create this constructor. Only one constructor, but now the
problem is in order to call it, I have to first create an array and
then pass it. This now creates extra work for me every time I wish to
construct my object template.

As a final option, which I pointed out, I could have the constructor
accept a std::vector, but then I still have to write at least one
other line of code to fill the std::vector with my values, unless they
all happen to be the same value.

--Jason
 
P

poorboywilly

The short answer is because the C++ syntax doesn't allow it. The longer
answer is that in general, objects have to exist somewhere. In the case
of temporary objects, this is normally on the stack, though compilers
are allowed to put them anywhere. Thing is, after the temporary goes
out of scope, the memory is reclaimed. This doesn't leave a lot of
options for temporary arrays. Most of the languages which allow what
you wrote also have garbage collectors tightly integrated with the
language. This more easily allows temporaries to be put in the garbage
collected heap, because you don't have to worry about leaking the
allocated memory. This kind of tight integration with a garbage
collector will never be the case in C++.

I don't quite see it...the compiler knows at compile time how big this
array is going to be, and that it will last the length of the function
call. It knows how much space to reserve on the stack and then how
much to take off when it is done.

--Jason
 
I

Ian Collins

poorboywilly said:
I don't quite see it...the compiler knows at compile time how big this
array is going to be, and that it will last the length of the function
call. It knows how much space to reserve on the stack and then how
much to take off when it is done.
Everything after the first sentence above is a bit of a red herring, the
most concise explanation was from Victor - 'There are no "array
literals" in C++ (beyond arrays of 'char const').'
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...

[ ... ]
So I guess my question is, why can I not initialize a function
argument with the array "shorthand" notation,

The reason you can't is simply that the language doesn't allow it.
There's really not a lot more to say beyond that -- there's no technical
reason something like this _couldn't_ be allowed, but it's not.

[ ... changed order of comments ]
I know I can use an STL container instead and pass an unnamed STL
container, but an STL container doesn't allow me to set construct it
with, say, 5 arbitrary values.

Actually, even though the constructor for the container doesn't support
initialization with an arbitrary number of arbitrary values, it's
possible to do it separately, if you want to badly enough:

// minimally tested...
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>

void f0(std::vector<int> const &v) {
// for now, just display the vector to show it's working.
std::copy(v.begin(), v.end(),
std::eek:stream_iterator<int>(std::cout, "\t"));
std::cout << "\n";
}

template<class T>
class make_vector {
std::vector<T> data;
public:
make_vector(T const &val) {
data.push_back(val);
}

make_vector<T> &operator,(T const &t) {
data.push_back(t);
return *this;
}

operator std::vector<T>() { return data; }
};

template<class T>
make_vector<T> makeVect(T const &t) {
return make_vector<T>(t);
}

int main() {
f0((makeVect(1), 2, 3, 4, 5));
f0((makeVect(1), 2, 3));
return 0;
}

Even I won't claim this is beautiful, but depending somewhat on your
taste, it might beat the alternatives. In case you're wondering, the
"extra" parentheses in the function calls are absolutely necessary.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,184
Messages
2,570,976
Members
47,533
Latest member
medikillz39

Latest Threads

Top