Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a C-array into a function which expects a C-array 'on the fly', without defining a variable

There exist many similar questions for C, e.g. this one, but i'm searching for the simplest and most readable way in C++ to pass an C-array into a function without first defining a variable for it.

Given a void f(double const* a) these are not possible (but the first one is in C99):

f((double []){1,2}); // works in C
f({1,2}); // would be great but doesn't work in any language with C-arrays

Of course defining a variable first is always possible, but that's not what i'm looking for:

double a[] = { 1.2, 3.4 };
f(a);

However, it is possible to wrap things into a struct, f.e. like

struct A { double a[2]; };
f(A{2.3,4.5}.a);

and that type can be reused, so that's already a little win

Live Demo

but this still feels clumsy.

Is there a simpler and more readable way? In one of the current standards or maybe an upcoming one?

EDIT: Sorry, i didn't mention that before; i can't change the target api. A pointer to a double is expected.

like image 776
ridilculous Avatar asked May 22 '26 22:05

ridilculous


2 Answers

This function is great for that:

template<typename T, std::size_t N>
constexpr T* temporary_array(T(&& arr)[N]) noexcept { return arr; }

Then you can simply call f(temporary_array<double>({1,2})); (or f(temporary_array({1., 2.}))).

In C++20, you can write f(std::type_identity_t<double(&&)[]>{1,2}). f(std::type_identity_t<double[]>{1, 2}) should also work in any C++ version, but GCC has a long-standing bug that doesn't allow this to compile.

Looking for standard library solutions, your struct A can be replaced with std::array<double, 2>. Writing out the size parameter is annoying, but it can be replaced with CTAD:

f(std::array{ 1., 2. }.data());
f(std::array<double, 2>{1, 2}.data());
// (These will call move constructors)
f(std::to_array<double>({1, 2}).data());
f(std::to_array({1., 2.}).data());
like image 143
Artyer Avatar answered May 24 '26 14:05

Artyer


How about you use a vector instead of a double*? Then you can construct one in-place even at call site, like so:

#include<vector>

double f(std::vector<double> const& v)
{
  return v[0];
}


int main()
{
  f({1,2,3});
}
like image 42
Michael Kopp Avatar answered May 24 '26 15:05

Michael Kopp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!