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.
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.
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.
}
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)
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.
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.
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.
Sadly, it only works with character arrays:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
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) );
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;
}
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);
}
Related
#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
#include <map>
#include <any>
using namespace std;
int func1(int a, int b, int c) {
return a + b + c;
}
int func1Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]), b = any_cast<int>(params["b"]), c = any_cast<int>(params["c"]);
return func1(a,b,c);
}
double func2(int a, int b) {
return a * b;
}
double func2Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]), b = any_cast<int>(params["b"]);
return func2(a,b);
}
int func3(int a, string b) {
return a + b.length();
}
int func3Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]);
string b = any_cast<string>(params["b"]);
return func3(a,b);
}
int func4(int a, vector<int> b) {
int sum = 0;
for (const auto& x : b) sum += x;
return a + sum;
}
int func4Wrapper(map<string, std::any> params)
{
int a = any_cast<int>(params["a"]);
auto b = any_cast<vector<int>>(params["b"]);
return func4(a,b);
}
typedef map<string, vector<map<string, any>>> FeatureMap;
vector<vector<std::any>> executor(map<string, vector<map<string, any>>> featureMap)
{
vector<vector<std::any>> res;
for (auto it=featureMap.begin(); it!=featureMap.end(); it++)
{
vector<std::any> currentRes;
if (it->first=="func1") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func1Wrapper(*paramIt));
}
if (it->first=="func2") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func2Wrapper(*paramIt));
}
if (it->first=="func3") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func3Wrapper(*paramIt));
}
if (it->first=="func4") {
for (auto paramIt=it->second.begin(); paramIt!=it->second.end(); paramIt++)
currentRes.push_back(func4Wrapper(*paramIt));
}
res.push_back(currentRes);
}
return res;
}
int main()
{
FeatureMap fm;
fm["func1"] = { {{"a", 1}, {"b", 2}, {"c", 3}} , {{"a", 3}, {"b", -4}, {"c", 5}} };
fm["func2"] = { {{"a", 2}, {"b", 2}} , {{"a", 3}, {"b", -4}} };
fm["func3"] = { {{"a", 3}, {"b", "hello"s}} , {{"a", 3}, {"b", "123"s}} };
fm["func4"] = { {{"a", 4}, {"b", vector<int>({1,2,3})}}, {{"a", 3}, {"b", vector<int>({3,4,5})}} };
auto res = executor(fm);
auto func1Res = res[0], func2Res = res[1], func3Res = res[2], func4Res = res[3];
cout << any_cast<int>(func1Res[0]) << " " << any_cast<int>(func1Res[1]) << "\n";
cout << any_cast<double>(func2Res[0]) << " " << any_cast<double>(func2Res[1]) << "\n";
cout << any_cast<int>(func3Res[0]) << " " << any_cast<int>(func3Res[1]) << "\n";
cout << any_cast<int>(func4Res[0]) << " " << any_cast<int>(func4Res[1]) << "\n";
return 0;
}
I am converting a Python library to C++, it uses dict() everywhere.
A 1-1 conversion is like the code above: an executor accept a list of function, each function can have different parameter types and length. I store the parameters in a map<string, std::any> params, and for each function I have to manually extract the parameter then manually call the function (like func1Wrapper).
This code is very tedious to use and update. More importantly, it's very slow since there are map and std::any everywhere. I wish to use template to do as much thing as possible at compile time.
Is there anyway to convert the above code to using template? The executor should be able to accept any function with any parameter (different length, different types, ...). Instead of using a map<string, std::any> params, a user must give the function parameters in the correct order.
Edit: if the above is impossible, then what should I use to achieve similar functionality? Basically, the executor should be able to perform:
vector<vector<std::any>> res;
vector<vector<vector<std::any>> param_list;
for (i=0; i<function_list.size(); i++):
{
vector<std::any> currentRes;
for (j=0; j<param_list[i].size(); j++)
currentRes.push_back(function_list[i](param_list[i][j]));
res.push_back(currentRes);
}
while using as much compile-time stuffs as possible.
The executor should be able to accept any function with any parameter (different length, different types, ...).
You can use a combination of perfect forwarding and variadic templates as shown below. In the program shown, the function template forwardToArbitFunc<> accepts any number of function call arguments and forwards each of them to another function(which is also passed as the first argument to the function template).
#include <iostream>
#include<string>
//this function template forwards its arguments to arbitrary function
template<typename T, typename... Ts> void forwardToArbitFunc(T g,Ts&&... xs)
{
g(std::forward<Ts>(xs)...); // forward all xs to g()
}
void func()
{
std::cout<<"parameterless func called"<<std::endl;
}
void func2(int a)
{
std::cout<<"one parameter func2 called"<<std::endl;
}
void func3(std::string a, int b)
{
std::cout<<"two parameter func3 called"<<std::endl;
}
void func4(std::string a, std::string b, float c, double d)
{
std::cout<<"four parameter func4 called"<<std::endl;
}
int main()
{
forwardToArbitFunc(func);
forwardToArbitFunc(func2, 3);
forwardToArbitFunc(func3, "some string", 5);
forwardToArbitFunc(func4, "some string", "another string", 4.4, 5.5);
return 0;
}
Demo
Just recently started C++ programming for micro-controllers, and I've ran into situations* where it would be convenient to have a non-static const field on a struct that is always guaranteed to have a fixed value (same for every instance of the sturct, ever).
Given a struct
struct S {
const uint8_t c; // Should always be 42
char v;
uint32_t arr[4];
}
I'd like c to be a constant value, and the same constant value every time. I would love to be able to use the convenience of brace initializer lists, for setting v and the members of arr like
S some_var = {'v', { 0, 1, 2, 3 } };
Since I'd like c to be a constant, I'm under the impression that I have to use an initializer list for setting c, such as S() : c(42) {}, which works just fine, as long as I don't try to also initialize arr, in which case I'm lost on how the list should look like. Is this doable using C++11? (Also interested in an answer if this is not doable in C++11, but in some newer standard.)
Example code:
#include <stdio.h>
#include <stdint.h>
struct S {
const uint8_t c; // Should always be 42 on every instance
// of the struct due to hardware shenanigance
// (i.e. this struct is the representation of a register value)
char v;
uint32_t arr[4];
// This allows using "S s1;"
S() : c(42), v('a'), arr{} {}
// This allows using "S s2 = { 'v', 0, 1, 2, 3 };" works but it's clumsy:
S(uint32_t v, uint32_t arr0, uint32_t arr1, uint32_t arr2, uint32_t arr3) :
c(42), v(v), arr{ arr0, arr1, arr2, arr3 } {}
// I would like to do something along the lines of "S s2 = { 'v', { 0, 1, 2, 3 } };":
// S(uint32_t v, uint32_t arr[4] /*?*/) :
// c(42), v(v), arr{/*?*/} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
// Initialiation like this works with the line:12 signature:
S s2 = { 'v', 0, 1, 2, 3 };
// I'd like to initialize like this:
// S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
*Context on why I'd want to do this: This might seem like a weird thing to want, since if the value is always the same, why bother storing it? Well imagine that the struct in question is a bitfield which corresponds to the register of an IC with which the micro-controller communicates. These registers sometimes have "reserved" fields, and the datasheet specifies what value you must write into these fields. From a programmer's point of view, it would be convenient if I never had to deal with setting said bits manually.
C++11 gives you std::array which is like a raw array, but comes with none of the "negatives" (array decay, can't copy). Using that you can get exactly what you want like
struct S {
const uint8_t c = 42;
char v = 'a';
std::array<uint32_t, 4> arr{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::array<uint32_t, 4> arr) : v(v), arr{arr} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
which outputs
s1.c = 42
s1.v = 'a'
s1.arr[3] = 0
s2.c = 42
s2.v = 'v'
s2.arr[3] = 3
If you absoluytley have to have a raw array in S then your other option is to use a std::initializer_list in the constructor. That would look like
struct S {
const uint8_t c = 42;
char v = 'a';
uint32_t arr[4]{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::initializer_list<uint32_t> data) : v(v)
{
int i = 0;
for (auto e : data)
arr[i++] = e;
}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
And you get the same results as the code using std::array.
I have designed a matrix class. Now I would like to initialize via list
Matrix3D m2{{1,2,3},{4,5,6},{7,8,9}};
instead of
Matrix3D m1(1,2,3,4,5,6,7,8,9);
I have added a static assert to force the size of the matrix which does not work.
How should I modify the constructor?
#include <iostream>
using namespace std;
class Matrix3D
{
int a11;
int a12;
int a13;
int a21;
int a22;
int a23;
int a31;
int a32;
int a33;
public:
Matrix3D(
int a11,
int a12,
int a13,
int a21,
int a22,
int a23,
int a31,
int a32,
int a33):
a11(a11),
a12(a12),
a13(a13),
a21(a21),
a22(a22),
a23(a23),
a31(a31),
a32(a32),
a33(a33)
{
}
Matrix3D(std::initializer_list<std::initializer_list<double>> listlist);
};
Matrix3D::Matrix3D(std::initializer_list<std::initializer_list<double>> listlist)
{
constexpr int rows = (int)(listlist.begin()).size();
constexpr int cols = (int)listlist.size();
static_assert(rows == 3, "");
static_assert(cols == 3, "");
a11=(listlist.begin()+0)[0];
a12=(listlist.begin()+0)[1];
a13=(listlist.begin()+0)[2];
a21=(listlist.begin()+1)[0];
a22=(listlist.begin()+1)[1];
a23=(listlist.begin()+1)[2];
a31=(listlist.begin()+2)[0];
a32=(listlist.begin()+2)[1];
a33=(listlist.begin()+2)[2];
}
int main() {
Matrix3D m1(1,2,3,4,5,6,7,8,9);
Matrix3D m2{{1,2,3},{4,5,6},{7,8,9}};
return 0;
}
I have added a static assert to force the size of the matrix which does not work.
Unfortunately for your situation std::initializer_list<Elem> is designed for a variable number of elements, which is why you cannot statically say anything about its size in the general case. The fact that its size member is constexpr is a red herring:
constexpr std::initializer_list<int> constant_expr = { 0, 2, 4, 6 };
// this is what a constexpr size member makes possible
static_assert( constant_expr.size() == 4 );
std::initializer_list<int> non_constant_expr = { 1, 3, 5 };
// this can't work
//static_assert( non_constant_expr.size() == 3 );
Function parameters are not constant expressions.
Instead, you would be better served by a type with a statically known number of elements. Array references can be suited to your needs:
class Matrix3D {
using index_type = int;
static constexpr index_type cols = 3;
using row_arg_type = int[cols];
public:
Matrix3D(row_arg_type const& row0, row_arg_type const& row1, row_arg_type const& row2);
// rest of class omitted
};
// number of rows and row width are statically enforced
Matrix3D m = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
Coliru demo
How can I find the index of the maximum value in a VexCL vector? I can find the maximum value:
int h[] = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, 5);
vex::copy(h, d);
vex::Reductor<int, vex::MAX> max(ctx.queue());
int m = max(d);
Which gives m = 5 but is there a way to find the index of the maximum value, ind = 3?
You will need to
encode both vector value and vector position in a vexcl expression, and
create custom functor for vex::Reductor that would reduce the above expression based on its first component.
Here is the working code:
#include <iostream>
#include <vector>
#include <vexcl/vexcl.hpp>
// This function converts two integers to cl_int2
VEX_FUNCTION(cl_int2, make_int2, (int, x)(int, y),
int2 v = {x, y};
return v;
);
// This struct compares OpenCL vector types by the first component.
struct MAX0 {
template <class Tn>
struct impl {
typedef typename vex::cl_scalar_of<Tn>::type T;
// Initial value.
static Tn initial() {
Tn v;
if (std::is_unsigned<T>::value)
v.s[0] = static_cast<T>(0);
else
v.s[0] = -std::numeric_limits<T>::max();
return v;
}
// Device-side function call operator
struct device : vex::UserFunction<device, Tn(Tn, Tn)> {
static std::string name() { return "MAX_" + vex::type_name<Tn>(); }
static std::string body() { return "return prm1.x > prm2.x ? prm1 : prm2;"; }
};
// Host-side function call operator
Tn operator()(Tn a, Tn b) const {
return a.s[0] > b.s[0] ? a : b;
}
};
};
int main(int argc, char *argv[]) {
vex::Context ctx( vex::Filter::Env );
std::vector<int> h = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, h);
// Create reductor based on MAX0 operation,
// then reduce an expression that encodes both value and position of a
// vector element:
vex::Reductor<cl_int2, MAX0> max(ctx);
cl_int2 m = max(make_int2(d, vex::element_index()));
std::cout << "max value of " << m.s[0] << " at position " << m.s[1] << std::endl;
}
This outputs
max value of 5 at position 3
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.
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.
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.
}
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)
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.
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.
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.
Sadly, it only works with character arrays:
void func2(char arg[]) {
}
int main()
{
func2("hello");
return 0;
}
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) );
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;
}
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);
}