Forward declare pointers-to-structs in C++ - c++

I am using a 3rd party library that has a declaration like this:
typedef struct {} __INTERNAL_DATA, *HandleType;
And I'd like to create a class that takes a HandleType in the constructor:
class Foo
{
Foo(HandleType h);
}
without including the header that defines HandleType. Normally, I'd just forward-declare such a type, but I can't figure out the syntax for this. I really want to say something like:
struct *HandleType;
But that says "Expected identifier before *" in GCC. The only solution I can see is to write my class like this:
struct __INTERNAL_DATA;
class Foo
{
Foo(__INTERNAL_DATA *h);
}
But this relies on internal details of the library. That is to say, it uses the name __INTERNAL_DATA, which is an implementation detail.
It seems like it should be possible to forward-declare HandleType (part of the public API) without using __INTERNAL_DATA (part of the implementation of the library.) Anyone know how?
EDIT: Added more detail about what I'm looking for.

Update:
I am using it in the implementation .cpp of Foo, but I want to avoid including it in my header .h for Foo. Maybe I'm just being too pedantic? :)
Yes you are :) Go ahead with forward declaration.
If HandleType is part of the interface there must be a header declaring that. Use that header.
Your problem is still a vague one. You are trying to protect against something you cannot.
You can add the following line to your client library:
typedef struct INTERNAL_DATA *HandleType;
but, if the name/structure changes you may be in for some casting nastiness.
Try templates:
template <class T>
class Foo
{
Foo(T h);
};
Forward declaration is fine. If you are going to use pointers or references you only need a class (__INTERNAL_DATA) declaration in scope. However, if you are going to use a member function or an object you will need to include the header.

If the type is in a 3rd party library then the big benefit of forward declaration (isolating rebuilds due to changes in headers) is effectively lost.
If you're worried about compilation times (it's a sizeable header) then perhaps you can place it in a precompiled header or just include the relevant header from a library.
E.g. many library headers look like
// library.h
#include "Library/Something.h"
#include "Library/SomethingElse.h"

typedef struct {} __INTERNAL_DATA, *HandleType;
If it is defined like that (all on one line), then __INTERNAL DATA is as much a part of the public interface as HandleType.
However, I don't think __INTERNAL_DATA actually exists. More than likely, HandleType is really (internally) an int. This odd definition is just a way of defining it so that it's the same size as an int, but distinct, so that the compiler give you an error if you try passing an int where you're supposed to pass an HandleType. The library vendor could just as easily have defined it as "int" or "void*", but this way we get some type checking.
Hence __INTERNAL_DATA is just a convention and is not going to change.
UPDATE: The above was a bit of a mental burp... OK, __INTERNAL_DATA definitely does not exist. We know this for a fact, because we can see it's definition as an empty struct. I'm going to guess that the 3rd-party library uses "C" external linkage (no name managling), in which case, just copy the typedef -- it will be fine.
Inside the library itself, HandleType will have a completely different definition; maybe int, maybe "struct MyStruct {.......} *".

If you really, really, really don't want to expose _INTERNAL_DATA to the caller then your only real choice is to use typedef void* HandleType; Then inside your library you can do anything you want including changing the entire implementation of *HandleType.
Just create a helper function to access you real data.
inline _INTERNAL_DATA* Impl(HandleType h) {
return static_cast<_INTERNAL_DATA*>(h);
}

I'm not quite sure what you're going for, but the following will work without including the actual header file:
// foo.h
class Foo
{
public:
template<typename T>Foo(T* h) { /* body of constructor */ }
};
Mind you, you will still have to have access the public members of __INTERNAL_DATA within the body of the constructor.
edit: as pointed out by James Curran, the __INTERNAL_DATA structure has no members, so it can be used, as above, with no problems.

Related

C++ Two Classes Template Methods Reference (Not Compose) Each Other

I've gotten into a bit of a design block in a C++ program of mine as two different header files are required to reference each other. Typically a forward declaration would be used here, but since both classes use template functions/constructors a forward declaration cannot be used as methods/variables from both classes need to be used.
For example consider the following scenario (this is pseudo code as an example, it may/may not compile. The objects are representative of my actual application so if a redesign is necessary then I'd love to understand the design philosophies of what I did wrong)
// Application.hpp
#include <Assets.hpp>
#include <Logger.hpp>
class Application {
public:
// Some brilliant code here ...
Logger myLogger;
template <int someArrayLen> Application(std::array<int, someArrayLen> myArr, SomeOtherTypes someOtherStuff) : myLogger(stuffHere) {
mainAssets = new Assets(myArr);
}
~Application(); // Assume this is implemented in Application.cpp and has delete mainAssets;
};
extern Application* mainApp; // Assume Application* mainApp = nullptr; in Application.cpp
// Assets.hpp
// #include <Application.hpp> ???? The issue lies here
class Assets {
private:
// Random data structures/stuff for holding shaders/textures/etc
protected:
template <int someArrayLen> Assets(std::array<int, someArrayLen> myArr) {
if (!shadersSupported()) {
// Main app is an unknown symbol
mainApp->myLogger->error("Your GPU is too old/whatever!");
}
// Random code for loading assets based on my template stuff
}
friend class Application;
public:
// Get assets/whatever here
};
extern Assets* mainAssets; // Assume Assets* mainAssets = nullptr; in Assets.cpp
How can I fix the compile error regarding mainApp being an unknown symbol? Any feedback/help is appreciated, thanks!
I've already looked through all the following questions but none address this unique scenario:
two classes referencing each other
This question had no use of templates so forward declarations could be used as the method bodies weren't defined in the headers
Two classes referencing each other with hash template specialization
The solution from this question cannot be used as here the compiler was unable to figure out how much memory to allocate, whereas in my question the issue isn't regarding the compiler being confused with how much to allocate but rather what to reference
Two template classes being composed of a member of each other
This question addressed a design flaw of circular dependencies which my application does not have, both classes are stored globally, they are just instantiated in separate constructors which reference each other.
Two classes that refer to each other
This question provides forward declarations as a solution which cannot be used here due to the requirement for using the class methods/constructors in template function definitions.
I've also already considered the following:
Trying to change from std::array to pointers, this wouldn't work as my Assets constructor does rely on the lengths of the array.
Trying to change from std::array to std::vector, I want to stick to aggregate initialization so it can be done at compile time, I believe vectors/lists would be too heavy for this.
Forward declarations will indeed work for your problem. The key is that function templates can be defined out of line (i.e., not in your class ... { }; declaration) legally. The same can be achieved for arbitrary functions using the inline keyword.
To now solve your specific problem, just split Application.hpp into Applicaton_fwd.hpp and Application.hpp - similar to iosfwd. Application_fwd.hpp contains almost all the code and Application.hpp includes Application_fwd.hpp and Assets.hpp before defining the Application::Application function template (just like you would define a function in a *.cpp file).
In Assets.hpp, you can simply use Application_fwd.hpp as long as you do not use the constructor. If you also use the Application constructor in Assets.hpp, things become a bit more complicated in that you need to very carefully consider all possible inclusion scenarios (i.e., what happens exactly every time one of your headers is included by themselves or a user) to make sure that it resolves in the order that you need it to without the guards causing trouble.
You can see it in action here

Hiding library dependencies from library users

Consider I'm writting a static library. Let it has a class Foo
// mylib.h
#include <dependency_header_from_other_static_library.h>
class Foo {
// ...
private:
type_from_dependent_library x;
}
As you can see this library (let call it mylib) depends on another library. It compiles well. But when user compile it's code (that uses Foo and includes mylib.h) and linking with my lib the compilation fails, because user need to have dependency_header_from_other_static_library.h header file to compile code as well.
I want to hide this dependency from the user. How this can be done? The one thing that comes to mind is a PIMPL idiom. Like:
// mylib.h
#include <dependency_header_from_other_static_library.h>
class Foo {
// ...
private:
class FooImpl;
boost::shared_ptr<FooImpl> impl_;
}
// mylib_priv.h
class FooImpl {
// ...
private:
type_from_dependent_library x;
}
But it requires me to duplicate the interface of the class Foo in FooImpl. And, is it an overkill to use PIMPL in my case?
Thanks.
When decoupling a header from other headers, there are a few approaches you might be able to use:
If the used library makes a promise about how it declares its types, you may be able to forward declare the needed types in your header. Of course, this still means you can only refer to these types as pointers or in function signatures in the header but this may be good enough. For example, if the used library promises to have a class LibraryType that you need to use, you can do something like this:
// Foo.h
class LibraryType;
class Foo {
// ...
LibraryType* data;
};
This may cut you the necessary slack to use the type without including its header and without jumping through a PImpl approach.
If the library doesn't make a promise about how it declares it types you may use void* to refer to the corresponding types. Of course, this means that whenever you access the data in your implementation, you'll need to cast the void* to the appropriate type. Since the type is statically known, using static_cast<LibraryType*> is perfectly fine, i.e., there isn't any overhead due to the cast, but it is still relatively painful to do.
The other alternative is, of course, to use the PImpl idiom. If you type provides any reasonably service, it will probably change the interface quite a bit and it shouldn't amount much to replicating the interface between the class itself and the privately declared type. Also, note that the private type is just a data container, i.e., it is reasonably to just make it a struct and have no protection to its accesses. The only real issue is that you need to make sure that the type's definition is visible at the point where the destructor is called. Using std::shared_ptr<T>(new T(/*...*)) arranges for this.
Effectively, all three approaches do the same thing although with slightly different techniques: they provide you an opaque handle to be used in the header file whose definition is only known to the implementation. This way, the client of the library doesn't need to include the corresponding header files. However, unless the symbols are resolved when building the library, it would still be necessary for the client to have access to the used library.

Central Typedefs.h file - is it a good idea?

Coming from the Java world, in which there are no typedefs, I have a question for C++ developers:
My task is to rewrite a large MATLAB project in C++. In order to get to know the structure of the code, I have started rebuilding the module and class structure without actually implementing the functionality.
I know that I frequently need classes/types like Vector and ParameterList, which will be provided by some framework I have not decided on yet.
So I created a central header file Typedefs.h in which I have type definitions like
typedef void Vector; // TODO: set vector class
typedef void ParameterList; // TODO: set parameter list class
For now, these are set to void, but I can use these types to write class skeletons and method signatures. Later I can replace them with the actual types.
Is this something that makes sense? If yes, is there a way to avoid manually including the Typedefs.h in every file?
I doubt this would work, unless you use, for example Vector*. You wouldn't be able to have Vector objects or parameters, so it's pretty much pointless.
And for use as a pointer, you can very well do a forward declaration.
Anyway, I don't really see the need for any of this. You can declare an empty class without having to implement it, and it's even easier to write than a typedef:
typedef void Vector;
vs
struct Vector{};
Note that you will not be able to overload functions with typedefs that map to the same type:
void foo(Vector);
void foo(ParameterList); // error: foo(void) already declared

What's the best strategy for typedef'ing shared pointers?

I have a quick question regarding the use of typedefs for lengthy templates. The crux: I've found myself in something of a pickle—there doesn't seem to be a good place to place typedefs except local to client functions. While there are similar SO questions (see here for example), none seem to address this exactly. Please note that this question doesn't address whether typedefs are desirable in what follows—I've tried to simplify things for expository purposes.
My problem has arisen while working with boost::shared_ptr<T>. Basically, I want to do the following:
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<Widget> WidgetPtr;
Placing this typedef in the Widget declaration header seems ugly. There seem to be two considerations here: (i) if Widget itself doesn't make use of shared pointers in its members, we've added an additional include (as we can't forward declare the boost::shared_ptr template class—correct me if I'm wrong?) (ii) if we want to make use of this typedef during the declaration of another class (call that class Foo) we violate best practices by including Widget.h instead of simply forward declaring Widget or including WidgetFwd.h... unless this typedef is duplicated in the latter. Furthermore, it doesn't seem make sense to typedef boost::shared_ptr<Widget> during the declaration of Widget itself—we seem to be mixing Widget's declaration with an anticipation of how clients will make use of the Widget interface.
Okay, so that's bad, but this is worse: if I don't attempt some combination of the above I end up with duplicate typedefs in client code, which yields inconsistency (and hence, likely, error)—the whole point being that given Widget, a WidgetPtr typedef should act as a type in its own right. Example: we don't want Foo to make use of one WidgetPtr, a typedef of boost::shared_ptr, while Bar is using WidgetPtr as a typedef for std::auto_ptr.
Another method (and one of the few that I've seen mentioned in online discussion) would be to make the typedef a public member of Widget and then use Widget::Ptr:
class Widget {
// ...
public:
typedef boost::shared_ptr<Widget> Ptr;
};
Again, I don't like this as (i) it suggests that the pointer type is somehow a member of the class and (ii) it leads to a wonky interface. Worse still: since every class that I write can potentially be pointed to using smart pointers, I end up chasing the imaginary client's tail. Ugly, ugly, ugly.
As it stands, I've removed the typedefs from this codebase (as they led to serious confusion, duplication) and re-introduced them locally in selected functions. Here again there's a problem with inconsistent usage but it's not quite as severe.
The only other solution I can think of—and again I'm not sure whether this is considered good practice—would be to have a utilities header in which the typedefs are placed, potentially within their own namespace. In this header we'd include and be done with it.
Am I missing something obvious or is this just plain tricky?
PS—Apologies for the length of the above; I couldn't find a simpler way of fully expressing the problem.
Furthermore, it doesn't seem make sense to typedef boost::shared_ptr during the declaration of Widget itself—we seem to be mixing Widget's declaration with an anticipation of how clients will make use of the Widget interface.
First of all, this is not at all wrong - after all, the means of how the clients will (and can) use the interface is part of the interface itself; and for C++, not being garbage-collected, memory management of objects is a rather crucial part of their interface.
So there are two cases. In one case, the Widget would anticipate it would be used through a shared pointer. This would mean that eg. child widgets obtained from a widget are returned as shared_ptrs, everywidget created has it shared_ptr and so on. It would be totally legitimate to typedef WidgetPtr in the same header as Widget.
In the second case, Widgets would expect to be managed eg. by ordinary new and delete. The clients can use shared_ptrs in special cases, but nothing says eg. a printer dialogue routine can't use auto_ptr instead. The clients have to be prepared that if wptr is a shared_ptr, the line
shared_ptr<Widget> w2(wptr->firstChild()->parent());
leads to a disaster.
Your question seems to indicate the latter is your case. So IMHO, what you've done is OK. The clients can choose their means of managing Widget objects, as long as it doesn't affect other clients.
I don't like a library dictating the use of a particular smart pointer, but I tolerate it if it is necessary.
If you wish to force users to always use a shared_ptr to manipulate a widget, it's impossible, so don't even bother trying.
On the other hand, if you have a method from Widget which returns a boost::shared_ptr<Widget>, then providing a (sane) typedef might simplify the client code.
I would therefore promote the use of an inner typedef:
class Widget
{
public:
typedef boost::shared_ptr<Widget> Ptr;
Ptr AccessFirstChild();
}; // class Widget
in which case it's perfectly okay to #include the necessary headers.
You are overthinking this in my opinion. Everybody who wants to have a shared_ptr<Widget> is going to have to include the Widget header file anyway. Putting the typedef (which is a good idea imo) in Widget.h makes 100% sense to me.
My approach (using underbar types, just because it is how I do it)
class Type
{
public:
typedef shared_ptr<Type> ptr;
typedef shared_ptr<const Type> const_ptr;
};
I have found the const_ptr version is pretty darn useful.
I used to structure my C++ code into libraries. A library would have a bunch of headers for client consumption, all inside the include/LibraryName directory. Also, I would have one header called Fwd.h inside this directory with forward declarations of all classes along with their pointer typedefs.
In addition, each public header would include Fwd.h so that including the header would automatically give you all forward declarations and pointer typedefs. This worked really well in practice.
Not all classes are necessary to place in a shared_ptr though. I would only create pointer typedefs for types that I expected to be created dynamically, and in this case I would supply a factory. This has the added benefit that you may get away with supplying client code with interface types only, and hide concreted implementations in your library's src directory. Not specifically what you asked advice for, but this gives the complete picture of my method. As a final point, it's also possible to supply a convenience header called LibraryName.h that includes the Fwd.h and all other public headers.
Good luck!
I generally use this approach to ease typing and makes a generic shared pointer interface for classes.
Do note it's C++0x.
#include <iostream>
#include <memory>
template <class T>
struct SharedVirtual
{
typedef std::shared_ptr<T> VPtr;
};
template <class T>
struct Shared
{
typedef std::shared_ptr<T> Ptr;
template <class... P>
static Ptr ptr(P&&... args)
{
return std::make_shared<T>(std::forward<P>(args)...);
}
};
class Foo : public SharedVirtual<Foo>
{
public:
virtual void foo() const = 0;
};
class Test : public Foo, public Shared<Test>
{
public:
void foo() const { std::cout << "Hai u!" << std::endl; }
};
void print(const Foo::VPtr& ptr)
{
ptr->foo();
}
int main()
{
auto ptr = Test::ptr();
print(ptr);
}
Second part first: use a namespace, i.e.:
namespace WidgetStuff {
class Widget { ..
typedef shared_ptr<Widget> WidgetPtr;
..
If you want to split it up:
namespace WidgetStuff {
class Widget { ...
}
...
namespace WidgetStuff {
typedef ...
You're the library author, you own the namespace, so no one else should invade it.
And now part one is answered too, if you choose you can do:
#include <widget.h>
#include <widget_utils.h>
by splitting up the namespace as above. The effect is no one has to use the utilities, whether or not they do they should not invade your namespace, so they're free to make WidgetPtr mean something else, as long as it isn't in your namespace.

forward declare static function c++

I want to forward declare a static member function of a class in another file. What I WANT to do looks like this:
BigMassiveHeader.h:
class foo
{
static void init_foos();
}
Main.cpp:
class foo;
void foo::init_foos();
int main(char** argv, int argc)
{
foo::init_foos()
}
This fails out with "error C2027: use of undefined type 'foo'"
Is there a way to accomplish what I want to do with out making init_foos a free function, or including BigMassiveHeader.h? (BigMassiveHeader.h is noticeably effecting compile time, and is included everywhere.)
You cannot forward declare members of a class, regardless of whether they are static or not.
You can't forward declare members of your class but you could make a namespace and a function inside of that namespace and forward declare that.
namespace nsfoo
{
void init_foos();
}
Your class if needed could friend this function.
If you have a BigMassiveHeader, you should consider splitting it up into several SmallCompactHeaders. If you want to express that many classes and functions belong together semantically, you can put them in the same namespace. You can always provide a convenience-header that includes all your small headers.
You can't partially declare classes in C++, so either you'll have to put the class's declaration in its own, smaller header, or...
Include BigMassiveHeader.h in your file and use precompiled headers.
The Visual C++ way: http://msdn.microsoft.com/en-us/library/2yzw0wyd%28v=VS.71%29.aspx, or the GCC way: http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html.
I know it's not the point of the question, but if BigMassiveHeader.h is not likely to change much over time, you should take a look at precompiled headers
As a first refactoring, I'd use a free function which calls the static function. It's not like your main method is getting called lots of times, so you won't notice an extra call, and that makes the least change to the existing code.
Of course, you don't actually say what you are trying to do, only what you want to do. If what you are trying to do is get init_foos called once on application start, use static object initialisation for that, rather than calling it in main. If what you are trying to do is get init_foos called after all static objects are created, then it's more complicated.
By static object initialisation, I mean something like having this in a .cpp file which has access to the definition of init_foos. Make it a friend and init_foos private to prevent multiple calls:
struct call_init_foos {
call_init_foos () { foo::init_foos(); }
} call_init_foos_on_startup;
to forward declaration of a single method of a class, you must declare the method as part of the class (as it really is).
for example, in your case, add to main.cpp:
class foo
{
public:
static void init_foos();
}
its not the prettiest, but it will save you having to include the whole header..
No, you need to include the header for that. Sorry.
Use a free function if you must, or split the class.