提问人:ModernEraCaveman 提问时间:8/6/2023 最后编辑:ModernEraCaveman 更新时间:8/6/2023 访问量:66
如何将模板参数与“if”和“switch”语句一起使用?
How do I use template parameters with "if" and "switch" statements?
问:
我目前正在用 Vulkan 用 C++ 编写游戏引擎,现在我正在努力将我的意大利面条代码简化为更直观的东西。作为此过程的一部分,我通用了一个描述符来创建引擎所需的多个组件,并且 由多个不同类型的对象继承。struct
struct
这在 my 和 objects 之间不是问题,因为它们都具有 type 的成员变量。但是,我的对象的不同之处在于成员变量的类型。SSBO
UBO
VkDescriptorBufferInfo
Texture
VkDescriptorImageInfo
对象使用这两种类型,其在“vulkan_core.h”标头中的定义是:VkWriteDescriptorSet
typedef struct VkWriteDescriptorSet {
VkStructureType sType;
const void* pNext;
VkDescriptorSet dstSet;
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
VkDescriptorType descriptorType;
const VkDescriptorImageInfo* pImageInfo; //to be provided by my Texture objects
const VkDescriptorBufferInfo* pBufferInfo; //to be provided by my UBO/SSBO objects
const VkBufferView* pTexelBufferView;
} VkWriteDescriptorSet;
我尝试概括对象的创建如下:VkWriteDescriptorSet
template <typename T>
inline VkWriteDescriptorSet writeSet(const std::vector<T>& bufferInfo, std::array<size_t,2> dst) {
VkWriteDescriptorSet writeInfo { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
/* Here I try to differentiate how the VkWriteDescriptorSet object is created */
if (std::is_same<T, VkDescriptorImageInfo>::value) {
writeInfo.pImageInfo = &bufferInfo[dst[1]]; //requires T == VkDescriptorImageInfo
}
else {
writeInfo.pBufferInfo = &bufferInfo[dst[1]]; //requires T == VkDescriptorBufferInfo
}
/* Then the function fills out the rest of the object */
return writeInfo;
}
上述内容在以下函数中调用:
void writeSets(uint32_t bindingCount) {
// The type of the vector below depends on the calling object (UBO/SSBO or Texture)
std::vector</* VkDescriptorBufferInfo or VkDescriptorImageInfo */> bufferInfo(bindingCount);
std::vector<VkWriteDescriptorSet> descriptorWrites(bindingCount);
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
/* loop does stuff */
for (size_t j = 0; j < bindingCount; j++) {
/* loop does more stuff */
descriptorWrites[j] = writeSet(bufferInfo, { i, j }); // the generalized function is called
}
vkUpdateDescriptorSets(VkGPU::device, bindingCount, descriptorWrites.data(), 0, nullptr);
}
}
不幸的是,我的程序无法编译并返回以下错误:
Severity: Error
Line: 27
Code: C2440
Description: '=': cannot convert from 'const _Ty *' to 'const VkDescriptorImageInfo *'
这最终引出了我的问题,如何在“if”和“switch”语句中使用模板参数?
编辑:
我尝试推广该函数的另一种方法是使用以下 switch 语句:VkDescriptorType
enum
template <typename T>
inline VkWriteDescriptorSet writeSet(const std::vector<T>& bufferInfo, std::array<size_t,2> dst) {
VkWriteDescriptorSet writeInfo { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
/* Here I try to differentiate how the VkWriteDescriptorSet object is created */
switch (type) {
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
writeInfo.pImageInfo = &bufferInfo[dst[1]]; //requires T == VkDescriptorImageInfo
default:
writeInfo.pBufferInfo = &bufferInfo[dst[1]]; //requires T == VkDescriptorBufferInfo
}
/* Then the function fills out the rest of the object */
return writeInfo;
}
答:
4赞
Jan Schultke
8/6/2023
#1
C++17
如果您使用的是 C++17,则解决方案非常简单。你可以变成:if
if constexpr
VkWriteDescriptorSet writeInfo { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
if constexpr (std::is_same_v<T, VkDescriptorImageInfo>) {
writeInfo.pImageInfo = &bufferInfo[dst[1]];
}
else {
// Optional assertion; ensures that were aren't working with some third type.
// This also documents our type expectation.
static_assert(std::is_same_v<T, VkDescriptorBufferInfo>);
writeInfo.pBufferInfo = &bufferInfo[dst[1]];
}
请注意,没有这样的东西,但是,您可以简单地编写一长串语句来达到相同的效果。switch constexpr
if constexpr ... else if constexpr
C++之前的17
在 C++17 之前,您可以简单地编写两个重载:
inline VkWriteDescriptorSet writeSet(const std::vector<VkDescriptorImageInfo>& bufferInfo,
std::array<size_t,2> dst) {
/* ... */
}
inline VkWriteDescriptorSet writeSet(const std::vector<VkDescriptorBufferInfo>& bufferInfo,
std::array<size_t,2> dst) {
/* ... */
}
没有太多的代码重复,所以在这种情况下应该没问题。如果函数较大,请考虑解决方案,例如模板的完整或部分专用化,仅针对不同且取决于特定类型的部件。T
评论
if
->if constexpr
(并且需要 C++ 17 或更高版本)typedef struct
在 C++ 中不需要。只要成功,它就会自动被 inedstruct VkWriteDescriptorSet { ... };
typedef
switch
if constexpr
else
typedef