Cie*_*ric 4 c++ templates typedef vulkan
在学习 Vulkan 时,我在 VulkanCookbook 中遇到了一些代码。在 VulkanCookbook 中,作者编写了手动导入 Vulkan 函数和类的代码。好吧,我一直在慢慢地将它转换为 Vulkan 的 LunarG SDK,我在 64 位 VkFence 下遇到了一个问题,它 typedef 到 VkFence_T* 这很好,但在 32 位中它被 typedef 为 uint64_t,这会导致VkDestroyer 使用类似于下面的代码的问题
#include <iostream>
#include <stdint.h>
typedef uint64_t A;
typedef uint64_t B;
template<typename T>
class Handler
{
void DestroyObject( T parent );
};
template<>
inline void Handler<A>::DestroyObject(A object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(B object) {
std::cout << "destroy type B!" << std::endl;
}
int main()
{}
Run Code Online (Sandbox Code Playgroud)
有什么好的方法可以解决这个问题,还是我必须重新编写所有示例代码以手动删除对象?如果可能,我想在 32 位下编译。
抱歉,如果在其他地方问过这个问题,我找不到它,因为 google 总是会出现部分模板和其他不相关的主题。而且我确实理解编译器正在查看 _A 和 _B 的代码的问题,并且只是将其视为 uint64_t 而不关心它们的名称不同,这会导致 DestroyObject 重载针对相同的模板类型,从而导致重新定义错误。
编辑:使用无效命名修复代码,因为这实际上不是核心问题。
C++ 没有强类型定义。类型别名只是现有类型的另一个名称,在使用时完全等同于它的别名类型。
您需要A和B成为实际类型,而不是别名,它们都与uint64_t. 只要您将自己限制在整数类型,您就可以从中构建新的不同类型。
解决方案是使用为其指定基础类型的枚举。
#include <type_traits>
template<typename E>
using argument_t = std::conditional_t<std::is_enum<E>::value,
std::underlying_type_t<E>,
E>;
template<typename T>
class Handler
{
void DestroyObject( argument_t<T> parent );
};
enum A : uint64_t {};
enum B : uint64_t {};
template<>
inline void Handler<A>::DestroyObject(uint64_t object) {
std::cout << "destroy type A" << std::endl;
}
template<>
inline void Handler<B>::DestroyObject(uint64_t object) {
std::cout << "destroy type B!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
上面的工作是这样的:
该argument_t实用程序检查是否E为枚举,并为其提供基础类型。否则它会退回到E它自己。
主模板接受 a T,并在需要时转换参数。
由于A和现在B是不同的类型,您可以专注于每个类型。该函数接受基础类型作为参数。