Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do smart pointers break the principle of minimizing #includes in header files?

Tags:

c++

I prefer to minimize the use of #include in my header files, using forward declarations wherever possible, and I believe this is considered good practice.

It works great if I have a method declaration like:

bool IsFlagSet(MyObject *pObj);

However if I have typedef Ptr<MyObject> MyObjectPtr in MyObject.h and the API changes to:

bool IsFlagSet(MyObjectPtr pObj);

Do I not now have to #include "MyObject.h"? Is there any way around this, or is it just the price one pays for using smart pointers?

like image 722
Mr. Boy Avatar asked Mar 22 '13 14:03

Mr. Boy


2 Answers

No, you do not have to. You can define a type alias for an incomplete class, and template arguments can be incomplete types (see Paragraph 14.3.1/2 of the C++11 Standard):

#include <memory>

struct C;

typedef std::shared_ptr<C> ptrC; // C is incomplete here

struct C { void foo() { } };

int main()
{
    ptrC p = std::make_shared<C>();
    p->foo();
}

As correctly mentioned by Pubby in the comments, function declarations do not require the types mentioned in their signature to be complete either:

struct C;

void foo(C); // C is incomplete here

struct C { };

#include <iostream>

void foo(C)
{
    std::cout << "foo(C)" << std::endl;
}

int main()
{
    C c;
    foo(c);
}
like image 187
Andy Prowl Avatar answered Nov 15 '22 09:11

Andy Prowl


No, std::shared_ptr<T> is explicitly designed to work when T is only forward-declared. Of course, this does not work for all cases, but the principle is the same as for a plain pointer. If T is forward-declared, you can do anything with std::shared_ptr<T> that you could do with T*.

like image 36
Daniel Frey Avatar answered Nov 15 '22 08:11

Daniel Frey