使用 typedef 的模板专业化

Template specialization using typedefs

在学习 Vulkan 时,我在 VulkanCookbook 中看到了一些代码。在 VulkanCookbook 中,作者手动编写了导入 Vulkan 函数和 类 的代码。好吧,我一直在慢慢地将它转换为 LunarG 的 Vulkan 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()
{}

有什么好的方法可以解决这个问题,还是我必须重新编写所有示例代码以手动删除对象?如果可能,我想在 32 位下编译。

抱歉,如果在其他地方有人问过这个问题,我找不到它,因为 google 总是出现部分模板和其他不相关的主题。而且我确实理解编译器正在查看 _A 和 _B 的代码的问题,只是将其视为 uint64_t 而不关心它们的命名不同,这导致 DestroyObject 重载用于导致重新定义的相同模板类型错误。

编辑:修复了使用无效命名的代码,因为这实际上不是核心问题。

你几乎是对的...上面的函数 Handler<_A>::DestroyObject(_A object)Handler<_B>::DestroyObject(_B object) 实际上是模板化成员函数的具体实例化。因为作者没有提供此函数的通用版本,所以您在尝试使用 uint32_t 实例化 class 时遇到了问题。简单的解决方法是编写一个 template<> void Handler<uint32_t>::DestroyObject(uint32_t o) 函数。没有更多的上下文,我无法提供更好的建议。

C++ 没有强类型定义。类型别名只是现有类型的另一个名称,并且在使用时完全等同于它作为别名的类型。

您需要 AB 是实际类型,而不是别名,它们都与 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;
}

上面的工作是这样的:

  • argument_t 实用程序检查 E 是否为枚举,并为其提供基础类型。否则它会退回到 E 本身。

  • 主模板接受 T,并根据需要转换参数。

  • 由于 AB 现在是 不同的 类型,您可以专注于每个类型。该函数接受基础类型作为参数。

模板无法区分作为类型参数传递的 AB

可能有手动清理对象的替代方法,但您的问题过于模糊,并且侧重于找到一种方法来让不可行的 solition 工作以确定您的问题到底是什么。

可能您必须使用与类型本身不同的东西来区分类型。