Reputation: 7682
If I have a prototype that looks like this:
function(float,float,float,float)
I can pass values like this:
function(1,2,3,4);
So if my prototype is this:
function(float*);
Is there any way I can achieve something like this?
function( {1,2,3,4} );
Just looking for a lazy way to do this without creating a temporary variable, but I can't seem to nail the syntax.
Upvotes: 48
Views: 43033
Reputation: 96326
In C++, you can pass std::array{ 1,2,3,4 }.data()
.
std::array{...}
creates a temporary array with a deduced element type, and .data()
returns a pointer to its first element.
Upvotes: 2
Reputation: 11037
In C++ you can bind a const
reference to a temporary. So if you don't need to write to the location, this will work:
void foo(const float (&a1)[4]) // clang needs the 4
{
}
foo((float[]){1,2,3,4});
Upvotes: 0
Reputation: 26813
I asked OpenAI Codex, and it suggested this method:
func((uint8_t *) "\x12\x34\x56\x78\x9a\xbc")
and it works in embedded C90, while the compound literals did not (syntax error near '{', expected 'sizeof'
).
Not really much benefit compared to creating a local scoped array, though:
{
uint8 da[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
func(da);
}
Upvotes: -1
Reputation: 116
To add to the fun, you can use templates to make it variable in length.
template<std::size_t N>
int chars(const char(&r)[N]){
std::cout << N << ": " << r << std::endl;
return 0;
}
template<std::size_t N>
int floats(const float(&r)[N]){
std::cout << N << ":";
for(size_t i = 0; i < N; i++)
std::cout << " " << r[i];
std::cout << std::endl;
return 0;
}
int main(int argc, char ** argv) {
chars("test");
floats({1.0f, 2.0f, 3.0f, 4.0f});
return 0;
}
Upvotes: 0
Reputation: 7258
You can technically take reference to array, but you still can't create anonymous initializer list I think.
void func(int (&bla)[4])
{
int count = sizeof(bla)/sizeof(bla[0]);
// count == 4
}
int bla[] = {1, 2, 3, 4};
func(bla);
int bla1[] = {1, 2};
func(bla1); // <-- fails
For C++ way, look at boost::assign. Pretty neat way of filling in STL containers.
Upvotes: 3
Reputation: 1716
you can write a builder class that would allow for about the same syntax
// roughly
template <typename C>
class Builder {
public:
template <typename T>
Builder(const T & _data) { C.push_back(_data); }
template <typename T>
Builder& operator()(const T & _data) {
C.push_back(_data);
return *this;
}
operator const C & () const { return data; }
private:
C data;
};
this way, you can use the class as
foo( const std::vector & v);
foo( Builder< std::vector >(1)(2)(3)(4) );
Upvotes: 0
Reputation: 400344
You can do it in C99 (but not ANSI C (C90) or any current variant of C++) with compound literals. See section 6.5.2.5 of the C99 standard for the gory details. Here's an example:
// f is a static array of at least 4 floats
void foo(float f[static 4])
{
...
}
int main(void)
{
foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f}); // OK
foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); // also OK, fifth element is ignored
foo((float[3]){1.0f, 2.0f, 3.0f}); // error, although the GCC doesn't complain
return 0;
}
GCC also provides this as an extension to C90. If you compile with -std=gnu90
(the default), -std=c99
, or -std=gnu99
, it will compile; if you compile with -std=c90
, it will not.
Upvotes: 47
Reputation: 503963
This is marked both C and C++, so you're gonna get radically different answers.
If you are expecting four parameters, you can do this:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(f);
}
But that is rather unsafe, as you could do this by accident:
void foo(float f[])
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2}; // uh-oh
foo(f);
}
It is usually best to leave them as individual parameters. Since you shouldn't be using raw arrays anyway, you can do this:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
float f[] = {1, 2, 3, 4};
foo(std::vector<float>(f, f + 4)); // be explicit about size
// assert says you cannot do this:
foo(std::vector<float>(f, f + 2));
}
An improvement, but not much of one. You could use boost::array
, but rather than an error for mismatched size, they are initialized to 0:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
boost::array<float, 4> f = {1, 2, 3, 4};
foo(f);
boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0}
foo(f2);
}
This will all be fixed in C++0x, when initializer list constructors are added:
#include <cassert>
#include <vector>
void foo(std::vector<float> f)
{
assert(f.size() == 4);
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4}); // yay, construct vector from this
// assert says you cannot do this:
foo({1, 2});
}
And probably boost::array
as well:
#include <boost/array.hpp>
void foo(boost::array<float, 4> f)
{
float f0 = f[0];
float f1 = f[1];
float f2 = f[2];
float f3 = f[3];
}
int main(void)
{
foo({1, 2, 3, 4});
foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure,
// I don't know if they will do the check, if possible.
}
Upvotes: 19
Reputation: 22133
Sadly, it only works with character arrays:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
Upvotes: 0
Reputation: 12047
You can create a compound literal:
function ((float[2]){2.0, 4.0});
Although, I'm not sure why you want to go through the trouble. This is not permitted by ISO.
Generally, shortcuts like this should be avoided in favor of readability in all cases; laziness is not a good habit to explore (personal opinion, of course)
Upvotes: 6
Reputation: 28198
No, you cannot do that. I do not have the standard available here, so I cannot give an exact reference, but the closest thing to what you ask for is string constants, i.e.
function(char *);
function("mystring");
is treated by the compiler as
char * some_pointer = "mystring";
function(char *);
function(some_pointer);
There is no way for other types of variables to be treated this way.
Upvotes: 0
Reputation: 12485
The bad news is that there is no syntax for that. The good news is that this will change with the next official version of the C++ standard (due in the next year or two). The new syntax will look exactly as you describe.
Upvotes: 2