-1

I've seen similar questions, but not quite like the predicament I find myself in. I'm working with someone else's code, and their structure is like this.

//db_manager.h
class db_manager
{
  class error;
  bool logError(error::def_enum::Value v, string msg);

  bool read(int id);
}

//db_manager.cpp
#include db_manager.h
bool logError(error::def_enum::Value v, string msg)
{
    return error::logError(v, msg);
}

bool read(int id)
{
    //do db access stuff
    return true;
}

//error.h
#include db_manager
class error
{
  bool read(int id);
}

//error.cpp
#include error.h
bool read(int id)
{
    return db_manager::read(id);
}

bool logError(error::def_enum::Value v, string msg)
{
    //do error service stuff
}

This is a pretty obvious simplification, but hopefully it demonstrates the issue.

When I compile, I get a lot of incomplete type errors whenever error is used in db_manager.cpp, and I can't include the relevant header files from error into db_manager.cpp, because then I have to add it to db_managers cmake dependencies, which means I have to list it in package.xml, and then it gets upset from the circular dependency. How can I get around this? If I could use error's members in db_manager without making error a dependency, I'd be good, I think, but I just can't figure out how to do that. I've seen many other forward-declaration questions on here, but for all of them, the declared class usage isn't very deep. Here I'm using class members, not just declaring a class pointer like other questions.

I definitely could use help, I just don't see any logical way to do this without completely scrapping the error package and writing a new one.

Edit: also, I simplified this out, but maybe I shouldn't have. error and db_manager are in two separate packages.

codechao
  • 67
  • 9
  • 1
    What you say about CMake and circular dependencies makes little sense. You can’t include the error header in the db_manager header, obviously, but including it `db_manager.cpp` should be perfectly fine. – idmean Mar 13 '19 at 12:22
  • Create a [mcve]. – eerorika Mar 13 '19 at 12:29
  • Circular header dependency is only a problem for headers. Since source files should generally never be included, they can't be part of a circular dependency problem. Though for reference, [here](https://stackoverflow.com/questions/4816698/avoiding-circular-dependencies-of-header-files) is a question about resolving them. – François Andrieux Mar 13 '19 at 12:32
  • db_manager and error are in 2 different packages. If I try to include the error header in db_manager.cpp, the compiler says it can't find it, and that is usually because the cmakelist and/or package.xml doesn't have the package that includes error in it as a dependency. And of course, if I add that, then we have a circular dependency. – codechao Mar 13 '19 at 12:39

1 Answers1

1

First: Your example is very bad. Please provide a minimum working example. I understand what your problem is (circular dependency), but your example is not showing this Problem. This is something you have to solve on an architectural level. You can't solve this inside CMake.

Depending on the Code you have shown you don't need to include db_manager.h in error.h, since you are not using anything from db_manager during the declaration of class Error. You only need to include it inside error.cpp, since there you are using one static method from db_manager. That way you don't have any circular dependency.

I have added a minimum working example below which compiles without any errors.

error.h

#ifndef _ERROR_H_
#define _ERROR_H_

#include <string>

class Error
{
public:
  enum def_enum{ Val1, Val2};

  bool read(int id);
  static bool logError(def_enum v, std::string msg);
};

#endif /* _ERROR_H_ */

error.cpp

#include "error.h"
#include "db_manager.h"

bool Error::read(int id)
{
    return db_manager::read(id);
}

bool Error::logError(Error::def_enum v, std::string msg)
{
    //do error service stuff
    return true;
}

db_manager.h

#ifndef _DB_MANAGER_H_
#define _DB_MANAGER_H_

#include <string>
#include "error.h"

class db_manager
{
public:
  static bool logError(Error::def_enum v, std::string msg);
  static bool read(int id);
};

#endif /* _DB_MANAGER_H_ */

db_manager.cpp

#include "db_manager.h"

bool db_manager::logError(Error::def_enum v, std::string msg)
{
    return Error::logError(v, msg);
}

bool db_manager::read(int id)
{
    //do db access stuff
    return true;
}

main.cpp

#include "db_manager.h"
#include "error.h"

int main(){


  db_manager::read(1);
  db_manager::logError(Error::Val1, "Test");

  Error e;
  e.read(2);

  return 0;
}

CMakeLists.txt

project(db_manager)

add_executable(executable main.cpp db_manager.cpp error.cpp)
A.K.
  • 861
  • 6
  • 12