3

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.

6
  • 3
    "so that's already a little win". Win for who? Certainly not for the next person reading your code. Commented Apr 24, 2023 at 12:30
  • In the first example, double *[] is a pointer to a pointer to double, not a poster to double. No way that's going to match. Commented Apr 24, 2023 at 12:30
  • @churill true but i can't change the target api in this case Commented Apr 24, 2023 at 12:42
  • @PeteBecker If with the first example you're referring to f((double *[]){1,2}); than that's the code from the question about the C-version i linked. I didn't change that code but added it for completeness sake. Is it more intuitive for the question if i remove it or add a title that it's from the C question? Commented Apr 24, 2023 at 12:47
  • 1
    I believe you confused things. Your linked C question intends to address an array of strings i.e. an array of arrays of chars. Hence, the char *[] makes sense. If you try to address an array of doubles, double *[] is plain wrong - in C as well as C++. Furthermore, I don't think referring to C is of much value here. C and C++ are different languages, and that something is correct in one of them doesn't necessarily mean anything for the other. Commented Apr 24, 2023 at 13:17

4 Answers 4

6

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());
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

1

If you can compile with c++20, the obvious answer is to use std::span, for maximum flexibility.

Demo:

#include <array>
#include <span>
#include <vector>

void f(std::span<const double> a);

int main()
{
    f({{1.0, 2.0, 3.3}});

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

    std::vector<double> v = { 1.2, 3.4 };
    f(v);

    std::array a = { 1.2, 3.4 };
    f(a);
}

Comments

1

If you want to avoid dynamic allocation, use std::initializer_list

template <typename T>
void f(const std::initializer_list<T>& v)
{
    for (const auto& e : v)
        std::cout << e << " ";
    std::cout << "\n";
}


int main()
{
    f({1,2,3});
    f({4.0,5.1,6.2});
}

outputs

1 2 3 
4 5.1 6.2 

Live example

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.