C++ 如何使用初始化列表创建std::array而不直接提供大小

C++ 如何使用初始化列表创建std::array而不直接提供大小,c++,initialization,stdarray,C++,Initialization,Stdarray,如何使a3编译 int main() { int a1[] = { 1, 2, 3 }; std::array<int, 3> a2 = { 1, 2, 3 }; std::array<int> a3 = { 1, 2, 3 }; } intmain() { int a1[]={1,2,3}; 数组a2={1,2,3}; 数组a3={1,2,3}; } 在使用初始化列表(尤其是长列表)时,对数组的大小进行硬编码是非常不方便和脆弱的。附近有工作吗

如何使
a3
编译

int main()
{
    int a1[] = { 1, 2, 3 };
    std::array<int, 3> a2 = { 1, 2, 3 };
    std::array<int> a3 = { 1, 2, 3 };
}
intmain()
{
int a1[]={1,2,3};
数组a2={1,2,3};
数组a3={1,2,3};
}

在使用初始化列表(尤其是长列表)时,对数组的大小进行硬编码是非常不方便和脆弱的。附近有工作吗?我希望如此,否则我会感到失望,因为我讨厌C数组,而
std::array
应该是它们的替代品。

如果不滚动您自己的
make_array
,目前没有办法做到这一点,对此有一个建议,其范围如下:

LWG 851旨在为

array<T, N> a = { E1, E2, ... };
格式良好(内部应用了其他静态类型转换),因为

array={42u,3.14};
格式良好

本文旨在提供一套std::array创建接口 从元组的角度和数组的角度来看都是全面的 从我的观点来看,缩小范围是自然禁止的。查看更多详细信息 在设计决策中受此方向的驱动

它还包括一个相当长的,因此在这里复制是不切实际的,但Konrad Rudolph有一个简化版本,与上面的示例实现一致:

template <typename... T>
constexpr auto make_array(T&&... values) ->
    std::array<
       typename std::decay<
           typename std::common_type<T...>::type>::type,
       sizeof...(T)> {
    return std::array<
        typename std::decay<
            typename std::common_type<T...>::type>::type,
        sizeof...(T)>{std::forward<T>(values)...};
}
模板
constexpr自动生成数组(T&&…值)->
std::数组<
typename std::decay<
typename std::common_type::type>::type,
大小…(T)>{
返回std::数组<
typename std::decay<
typename std::common_type::type>::type,
sizeof…(T)>{std::forward(values)…};
}

当你说“需要一个如此复杂(对我来说)的函数”时,你有点夸张了。您可以自己制作一个简化版本,该方案还包括一个“to_array”函数,用于转换C数组并从第一个参数推断类型。如果你不考虑这一点,它会变得相当容易管理

template<typename T, typename... N>
auto my_make_array(N&&... args) -> std::array<T,sizeof...(args)>
{
    return {std::forward<N>(args)...};
}
模板
自动生成数组(N&&…args)->std::array
{
返回{std::forward(args)…};
}
你可以这样称呼它

auto arr = my_make_array<int>(1,2,3,4,5);
auto arr=my_make_数组(1,2,3,4,5);
编辑:我应该提到的是,提案中实际上有一个版本我忽略了,因此这应该比我的版本更正确:

template <typename V, typename... T>
constexpr auto array_of(T&&... t)
    -> std::array < V, sizeof...(T) >
{
    return {{ std::forward<T>(t)... }};
}
模板
constexpr自动数组(T&…T)
->标准::数组
{
返回{{std::forward(t)…};
}

您可以实现自己的
make\u array()
函数。谢谢,这很有帮助,我可能会使用它。但是,当一个如此复杂的函数(对我来说)被要求去做C在30年前可以做的事情时,不知怎么的,我觉得它错了。此外,我担心我的编译器不够聪明,无法将其编译为与我自己的大小完全相同的大小。C++17是为这种情况引入的,但您必须忽略模板参数。是的,但您可以使用它来存储
std::vector
?生成
std::array
的向量需要所有大小都相同吗?@Brandon不幸的是,我认为它们需要相同的大小。忘记我在另一个线程中的建议:(@Brandon
std::vector
AFAIK是不可能的。是否有任何原因不能在最后一个示例中使用返回类型推断,或者只是
return{std::forward(values)…}
?上面@Konrad Rudolph的简化版
make_array()
会比中间版更好(更新后的原问题)发帖了?各有哪些优点和缺点?是的,哇,第二个例子在大多数情况下都很好用,一点也不复杂。谢谢!两个建议的实现之间的唯一区别是额外的一组花括号?这对看似不必要的大括号在语法上有什么区别?补充一下这些评论(虽然很晚了),双大括号与std::array初始化有关。我认为
{std::forward(args)…};
起作用的原因是省略大括号的规则稍微放宽了一点。
auto arr = my_make_array<int>(1,2,3,4,5);
template <typename V, typename... T>
constexpr auto array_of(T&&... t)
    -> std::array < V, sizeof...(T) >
{
    return {{ std::forward<T>(t)... }};
}