I am using an API that expects a contiguous block of memory that contains pointers.
the pointers themselves can be nullptr
.
Currently, I use C-Arrays:
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));
My toolchain contains clang-tidy, which advises to avoid C arrays and prefer std::array
instead.
std::array
has a deduction guide, that lets me initialize such an array like this:
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
};
This only works when the first element and all following elements are implicitly convertible to the same (pointer) type, in this case ID3D11ShaderResourceView*
.
It breaks apart, as soon as the first element contains a 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
};
makes sense, because the first element has the type std::nullptr_t
.
Can I initialize/deduce an std::array
without specifying the type explicitly and allow the first element to be nullptr
?
I could cast the first (nullptr
) element, but then I could just write it in the type as well.
I think you'll need to create a helper function that can deduce the type for you:
#include <array>
#include <type_traits>
#include <utility>
template<typename... T>
constexpr auto make_array(T&&... args)
-> std::array<std::common_type_t<T...>, sizeof...(T)>
{
return { std::forward<T>(args)..., };
}
Then we can write:
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
);