我使用的 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
) 元素,但随后我也可以将其写入类型中。
我认为您需要创建一个辅助函数来为您推断类型:
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
};