C 有很多类似的问题,例如这个,但我正在寻找 C++ 中最简单和最易读的方法来将 C 数组传递给函数,而无需先为其定义变量。
给定一个
void f(double const* a)
这些是不可能的(但第一个在C99中):
f((double *[]){1,2});
f({1,2});
当然总是可以先定义一个变量,但这不是我要找的:
double a[] = { 1.2, 3.4 };
f(a);
但是,可以将事物包装到一个结构中,例如。喜欢
struct A { double a[2]; };
f(A{2.3,4.5}.a);
而且那个类型可以重复使用,所以这已经是小赢了
但这仍然感觉笨拙。
有没有更简单易读的方式?在当前标准之一或即将推出的标准中?
编辑:抱歉,我之前没有提到;我无法更改目标 api。一个指向 double 的指针是预期的。
这个功能非常适合:
template<typename T, std::size_t N>
constexpr T* temporary_array(T(&& arr)[N]) noexcept { return arr; }
然后你可以简单地调用
f(temporary_array<double>({1,2}));
(或f(temporary_array({1., 2.}))
)。
在C++20中,你可以写
f(std::type_identity_t<double(&&)[]>{1,2})
。 f(std::type_identity_t<double[]>{1, 2})
也应该在任何 C++ 版本中工作,但 GCC 有一个长期存在的错误,不允许它编译。
寻找标准库解决方案,您的
struct A
可以替换为std::array<double, 2>
。写出size参数很烦人,不过可以用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());
你用
vector
代替 double*
怎么样?然后你甚至可以在调用站点就地构建一个,如下所示:
#include<vector>
double f(std::vector<double> const& v)
{
return v[0];
}
int main()
{
f({1,2,3});
}
如果你可以用 c++20 编译,显而易见的答案是使用 std::span,以获得最大的灵活性。
#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);
}
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});
}
输出
1 2 3
4 5.1 6.2
你的函数签名是错误的。它可以修复和改进。请参阅:https://godbolt.org/z/WoME5xazr
#include <iostream>
void foo(double (&arr)[])
{
std::cout<<arr[0]<<std::endl;
}
template<size_t N>
void BetterFoo(double (&arr)[N])
{
for (size_t i = 0;i<N;++i)
{
std::cout<<arr[i]<<std::endl;
}
}
int main()
{
double a[] = { 1.2, 3.4 };
foo(a);
std::cout<<"better foo"<<std::endl;
BetterFoo(a);
return 0;
};
希望有帮助