Opaque struct in C++ as class member

182 Views Asked by At

I have not been able to find an answer on this, but my case is:

// vulkan_glfw_backend.hpp
struct alignas(8) VulkanGlfwWindowContext;

class MY_API VulkanGlfwBackend
{
    // [...]
private:
    VulkanGlfwWindowContext* mpContext;
};

And the source file, where I want to have the implementation:

// vulkan_glfw_backend.cpp
#include "vulkan_glfw_backend.hpp"

struct VulkanGlfwWindowContext
{
    int numWindows;
    GLFWwindow* windows[MAX_WINDOWS];
};

Initially, my compiler complained because it couldn't determine the alignment requirements for the class, which I suppose makes sense. Then I added the alignas attribute. But now I get an error message, which I cannot understand the logical reason for:

vulkan_glfw_backend.cpp:113:51: error: invalid use of incomplete type ‘struct VulkanGlfwWindowContext’
  113 |                 for (int i = 0; i < mpContext->numWindows; i++)

Since I declare it explicitly as a pointer inside a class, the storage requirements should be clear. Additionally, it's an implementation detail how the memory layout of the struct looks, which the compiler knows at compile-time, because it is defined at the top of the source file.

So, why is this going wrong, and can I fix it somehow? For several reasons I desire to have an opaque type. Thanks!

1

There are 1 best solutions below

8
On

Answering my own question :)

So this is one of those days, where I'm not completely posting the entire code as is (my apologies!). So, the entire thing is inside a namespace:

// header
namespace mynamespace
{
    // vulkan_glfw_backend.hpp
    struct alignas(8) VulkanGlfwWindowContext;
}

//source
#include "vulkan_glfw_backend.hpp"
using namespace mynamespace;

struct VulkanGlfwWindowContext
{
    int numWindows;
    GLFWwindow* windows[MAX_WINDOWS];
};

The reason for this going wrong - again, I don't understand the logics behind it. Anyways, this is the fix:

//source
struct mynamespace::VulkanGlfwWindowContext
{
    int numWindows;
    GLFWwindow* windows;
};

Apparently, C++ doesn't understand the definition without fully-qualified namespace prepended to the name. I have seen the same issue with functions - it is not enough to open the namespace, it must be included in the definition.

This confuses me, as it is not required when implementing class member functions, where the name of the class is sufficient, e.g. someclass::somemember() {}.

But it works now!