1

I am building a C++ library. I have a struct that contains a std::unique_ptr to another struct that I would like to hide from the user.

For example:

struct MyStruct {
    int x;
  private:
    std::unique_ptr<MyPrivateStruct> y;
};

Now, I need to specify MyStruct in a header file that the user can include so that they know its layout. However, this requires that I also expose the header for MyPrivateStruct, which I do not want to do. Since the size of a unique_ptr is the same regardless of the type, is it possible to do something like this?

struct MyStruct {
    int x;
  private:
    std::unique_ptr<auto> y;
};

The type of the y would then be determined by my cpp files.


This is not quite the same question as Can't use std::unique_ptr<T> with T being a forward declaration since the answer to this question is to use a forward declaration. That question is about a problem when using forward declarations.

Community
  • 1
  • 1
sdgfsdh
  • 24,047
  • 15
  • 89
  • 182
  • Just forward declare the struct? Or is that what you are trying to avoid doing? – Borgleader Nov 23 '16 at 15:10
  • 3
    Possible duplicate of [Can't use std::unique\_ptr with T being a forward declaration](http://stackoverflow.com/questions/28386185/cant-use-stdunique-ptrt-with-t-being-a-forward-declaration) – LogicStuff Nov 23 '16 at 15:12
  • @LogicStuff not quite; see edit. – sdgfsdh Nov 23 '16 at 15:21
  • You don't need to expose the header for `MyPrivateStruct`. You need to forward declare it, which is one line: `struct MyPrivateStruct;` The client doesn't need to know anything about its definition in its header file. – jaggedSpire Nov 23 '16 at 15:23

2 Answers2

4

Sure!

struct MyPrivateStruct;

struct MyStruct {
    int x;
  private:
    std::unique_ptr<MyPrivateStruct> y;
};
Edward Strange
  • 38,861
  • 7
  • 65
  • 123
  • 2
    Although for me in Visual Studio it seems I have to create an empty destructor in MyStruct and define it in the cpp file instead of using the default to get it to compile because of the incomplete type. Like in this answer: http://stackoverflow.com/a/9954553/487892 – drescherjm Nov 23 '16 at 15:20
  • 1
    @drescherjm Yes you do. `~unique_ptr` will call the destructor of whatever its templated type is. If you allow the default destructor to be generated, it can't see the definition of `~MyPrivateStruct` because it is only forward declared at that point. – lcs Nov 23 '16 at 15:26
  • Yeah, part of the pain. If you use shared_ptr instead you don't have that problem, but I wouldn't recommend using it just because of that. – Edward Strange Nov 23 '16 at 16:41
2

MyPrivateStruct in std::unique_ptr<MyPrivateStruct> y; does not have to be a complete type.

That is, you can forward declare it by writing

struct MyPrivateStruct;

prior to the declaration of y.

  • 3
    Wrong. C++ standard does not insist on it. See https://gcc.gnu.org/wiki/FAQ#Why_GCC_does_not_warn_for_mismatch_between_struct_and_class_.28-Wmismatched-tags.29_.3F – SergeyA Nov 23 '16 at 15:25
  • 3
    Oh wow, I didn't know that. Perhaps I shouldn't base my knowledge solely on my Microsoft toolchain. Thank you so much, – Fitzwilliam Bennet-Darcy Nov 23 '16 at 15:26
  • 2
    @FitzwilliamBennet-Darcy VC++ doesn't comply with the standard on a [number of fronts](https://msdn.microsoft.com/en-us/library/x84h5b78(v=vs.140).aspx) – jaggedSpire Nov 23 '16 at 15:40