c++ - Vulkan-hpp 正在将非标准布局类重新解释为另一个类。这是合法的吗?

标签 c++ language-lawyer vulkan strict-aliasing

最近我一直在使用 Vulkan-Hpp(Vulkan Api 的官方 c++ 绑定(bind),Github Link)。

查看源代码,我发现他们围绕原生 Vulkan 结构创建了包装器类(例如 vk::InstanceCreateInfo 围绕着 VkInstanceCreateInfo)。 (注意:环绕,而不是派生自)

调用 native Vulkan API 时,指向包装器类的指针被 reinterpret_cast 编辑到 native Vulkan 结构中。使用 vk::InstanceCreateInfo 的示例:

//definition of vk::InstanceCreateInfo
struct InstanceCreateInfo
{
    /*  member function omitted  */
private:
  StructureType sType = StructureType::eInstanceCreateInfo;
public:
  const void* pNext = nullptr;
  InstanceCreateFlags flags;
  const ApplicationInfo* pApplicationInfo;
  uint32_t enabledLayerCount;
  const char* const* ppEnabledLayerNames;
  uint32_t enabledExtensionCount;
  const char* const* ppEnabledExtensionNames;
};

//definition of VkInstanceCreateInfo
typedef struct VkInstanceCreateInfo {
    VkStructureType             sType;
    const void*                 pNext;
    VkInstanceCreateFlags       flags;
    const VkApplicationInfo*    pApplicationInfo;
    uint32_t                    enabledLayerCount;
    const char* const*          ppEnabledLayerNames;
    uint32_t                    enabledExtensionCount;
    const char* const*          ppEnabledExtensionNames;
} VkInstanceCreateInfo;

//And the usage where reinterpret_cast takes place
template<typename Dispatch>
VULKAN_HPP_INLINE ResultValueType<Instance>::type createInstance( const InstanceCreateInfo &createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d )
{
  Instance instance;
  Result result = static_cast<Result>( d.vkCreateInstance( reinterpret_cast<const VkInstanceCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkInstance*>( &instance ) ) );
  return createResultValue( result, instance, VULKAN_HPP_NAMESPACE_STRING"::createInstance" );
}

所以我的问题是:vk::InstanceCreateInfoVkInstanceCreateInfo 是两种不同的类型。此外,VkInstanceCreateInfo 是标准布局,但 vk::InstanceCreateInfo 不是(因为它具有混合访问说明符)。在这两种类型的指针之间进行 reinterpret_cast(由 Vulkan-Hpp 完成)是否合法?这是否违反了严格的别名规则


注意:您可以假设 VkInstanceCreateFlagsvk::InstanceCreateFlags 在这种情况下可以互换(否则会使我的问题递归)

最佳答案

就标准而言,是的,通过指向 VkInstanceCreateInfo 对象的指针访问 vk::InstanceCreateInfo 对象违反了严格的别名。即使两种类型都是具有等效布局的标准布局,它仍然会违反严格的别名。该标准不允许您假装一种类类型是另一种类类型,即使它们具有相同的布局也是如此。

所以这段代码依赖于一些特定于实现的行为。

错了吗?为每个 Vulkan 接口(interface)函数调用做一个额外的拷贝会让你感觉更好吗,即使没有它也能工作?最终取决于您愿意容忍多少 UB。

关于c++ - Vulkan-hpp 正在将非标准布局类重新解释为另一个类。这是合法的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56985831/

相关文章:

c++ - 从 C++ Qt 5.2.1 更改 QML 文本框中的文本

c++ - Vulkan:转储当前分配的对象?

c++ - 派生 `VkMemoryRequirements`

c++ - C++11 和 C++14 中 `bsearch` 的规范是否有缺陷?

c++ - 具有 3 个组件的 Vulkan vkCreateImage

c++ - 将 float 转换为 unsigned short 时出现舍入问题

c++ - 有符号和无符号之间的减法,然后是除法

c++ - 为什么分配函数通过引用而不是值来获取 std::nothrow_t?

c++ - std::launder 和严格的别名规则

c++ - 函数参数中的省略号是否使用与普通参数相同的调用布局