111111
111111

Reputation: 16158

Failure to compile incomplete types; circular dependencies

Hi am having problems compiling some code, I have a situation where A depends and B depends on A. I have put forward declarations but I keep getting the problems.

In file included from src/MemoWriteContext.h:7:0,
                  from src/MemoWriteContext.cpp:1:
src/MemoContext.h:29:20: error: field ‘memoWriteContext’ has incomplete type

MemoContext.h

#ifndef MEMOCONTEXT_H_
#define MEMOCONTEXT_H_

#include "sqlite/SqliteDb.h"
#include "Context.h"
#include "MemoWriteContext.h"

#include <string>
#include <memory>
#include <map>

namespace bbs
{
    class MemoWriteContext;

    class MemoContext : public Context
    {
    public:
        //'structors
        MemoContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
                    sqlitecpp::SqliteDb &_sqliteDb);
        ~MemoContext();

    protected:
        //when called write the data back to the user
        void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);

    private:
        MemoWriteContext memoWriteContext;
    }; //class memocontext
}

#endif  // MEMOCONTEXT_H_

MemoWriteContext.h

#ifndef MEMOWRITECONTEXT_H_
#define MEMOWRITECONTEXT_H_

#include "Context.h"
#include "sqlite/SqliteDb.h"
#include "sqlite/PreparedStmt.h"
#include "MemoContext.h"

#include <string>
#include <memory>
#include <map>

namespace bbs
{
    class MemoContext; //forward decl

    class MemoWriteContext : public Context
    {
    public:
        //'structors
        MemoWriteContext(const std::map<std::string, std::shared_ptr<Context> > &_contexts,
                        MemoContext &_memoContext, sqlitecpp::SqliteDb &_sqliteDb);
        ~MemoWriteContext();

    protected:
        //when called write the data back to the user
        virtual void performAction(const std::string &data, std::shared_ptr<UserAgent> agent);
        virtual void onReceiveUserAgent(std::shared_ptr<UserAgent> agent);
    private:
        MemoContext &memoContext; //parent;
        sqlitecpp::SqliteDb &sqliteDb;
        sqlitecpp::PreparedStmt writeMemoStmt;  
        sqlitecpp::PreparedStmt findAgentIdStmt;    
    };

    enum class MemoWriteState : char
    {
        USERNAME=0,
        MESSAGE,
        CONFIRM
    };  

    class MemoWriteAgentData : public ContextAgentData
    {
    public:
        MemoWriteState state;
        int userId;
        std::string message;    
    }; //class Memo Write Agent data

}

#endif  // MEMOWRITECONTEXT_H_

Full source here.

Upvotes: 2

Views: 261

Answers (2)

Ben Jackson
Ben Jackson

Reputation: 93770

I think your only problem is that MemoWriteContext.h has #include "MemoContext.h". The context only requires a reference which can use the forward declaration. But if you happen to include MemoWriteContext.h first it will then bring in MemoContext.h before it actually declares class MemoWriteContext. That will then use the forward declaration of class MemoWriteContext and fail. You can even see the ordering in your error message.

Just remove that #include or at least reverse the order of the includes in MemoWriteContext.cpp (since each .h including the other effectively reverses them back).

Upvotes: 3

Etienne de Martel
Etienne de Martel

Reputation: 36946

This:

class MemoWriteContext;

Is a forward declaration. It's an "incomplete type", and therefore cannot be instantiated.

The reason is that a C++ compiler must know the size of any type that has to be instantiated. Incomplete types have no size.

By the way, you can do this:

MemoWriteContext * ptr;

Because you actually declare a pointer, and pointers have a known size.

If you want to avoid dynamic allocations, then you'll have to fully declare the type by including MemoWriteContext.h and removing the forward declaration.

Upvotes: 1

Related Questions