使用 nullptr 初始化 std::array 而不使用模板参数

问题描述 投票:0回答:1

我使用的 API 需要包含指针的连续内存块。 指针本身可以是

nullptr

目前,我使用 C 数组:

ID3D11ShaderResourceView* srvs[] = {
    room_diffuse_srv.Get(),
    lightmap_srv.Get(),
    room_normal_srv.Get(),
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    input.ambient_occlusion,
    reflection_srv.Get(),
    reflection_extents_srv.Get(),
    nullptr,
    nullptr,
    nullptr
};
ctx->VSSetShaderResources(0, UINT(std::size(srvs)), std::data(srvs));

我的工具链包含 clang-tidy,建议避免使用 C 数组并更喜欢

std::array

std::array
有一个推导指南,它可以让我像这样初始化这样的数组:

std::array srvs = {
    room_diffuse_srv.Get(),
    lightmap_srv.Get(),
    room_normal_srv.Get(),
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    input.ambient_occlusion,
    reflection_srv.Get(),
    reflection_extents_srv.Get(),
    nullptr,
    nullptr,
    nullptr
};

仅当第一个元素和所有后续元素都隐式转换为相同(指针)类型时才有效,在这种情况下

ID3D11ShaderResourceView*

一旦第一个元素包含 nullptr,它就会崩溃:

std::array srvs = {
    nullptr,
    lightmap_srv.Get(), // error: "a value of type "ID3D11SamplerState *" cannot be used to initialize an entity of type "std::_Enforce_same<std::nullptr_t, std::nullptr_t, ID3D11SamplerState *, std::nullptr_t, std::nullptr_t, ID3D11SamplerState *>::type" (aka "std::nullptr_t")"
    room_normal_srv.Get(),
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    input.ambient_occlusion,
    reflection_srv.Get(),
    reflection_extents_srv.Get(),
    nullptr,
    nullptr,
    nullptr
};

有道理,因为第一个元素的类型为

std::nullptr_t

我可以在不明确指定类型的情况下初始化/推导

std::array
并允许第一个元素为
nullptr
吗? 我可以投射第一个 (
nullptr
) 元素,但随后我也可以将其写入类型中。

c++ arrays stdarray
1个回答
0
投票

我认为您需要创建一个辅助函数来为您推断类型:

template<typename... T>
auto make_array(T&& ...args)
    -> std::array<std::common_type_t<T...>, sizeof... (T)>
{
    return { args..., };
}

然后我们可以写:

auto srvs = make_array(
    nullptr,
    lightmap_srv.Get(),
    room_normal_srv.Get(),
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    nullptr,
    input.ambient_occlusion,
    reflection_srv.Get(),
    reflection_extents_srv.Get(),
    nullptr,
    nullptr,
    nullptr
};
© www.soinside.com 2019 - 2024. All rights reserved.