0

Why it is okay when define op_and* operator&(data& left, data& right) in op.h

/* data.h */
#ifndef _DATA_H
#define _DATA_H
#include <string>
#include <utility>
#include "node.h"
#include "op.h"

struct data: node{
    std::string name;
    int width;
};

#endif //_DATA_H

/* op.h */
#ifndef _OP_H
#define _OP_H
#include <string>
#include <utility>
#include "node.h"
#include "data.h"

struct op: node {
    const std::string symbol;
    explicit op(data& left, data& right, std::string symbol):
    node(left, NODES::EMPTY, right), symbol(std::move(symbol)){}
};

struct op_and: op{
    explicit op_and(data& left, data& right):
    op(left, right, "&"){}
};

op_and* operator&(data& left, data& right){
    return new op_and(left, right); // it is okay here
}
#endif //_OP_H

But when define it data.h, IDE hints No matching constructor for initialization of "op_and"?

/* data.h */
#ifndef _DATA_H
#define _DATA_H
#include <string>
#include <utility>
#include "node.h"
#include "op.h"

struct data: node{
    std::string name;
    int width;
};

op_and* operator&(data& left, data& right){
    return new op_and(left, right); // here is error, cannot find op_and(data&, data&)
}

#endif //_DATA_H

This does look like a Circular dependency problem. I made a mistake. When I tried to include op.h in data.h, I get something like:

#ifndef _DATA_H
#define _DATA_H

#include <string>
#include <utility>
#include "node.h"

#ifndef _OP_H
#define _OP_H

/* including "op.h" starts */
#include <string>
#include <utility>
#include "node.h"
#include "data.h" // this will introduce nothing because _DATA_H is already defined

struct op: node {
public:
    const std::string symbol;
    symbol(std::move(symbol)){}
    explicit op(data& left, data& right, std::string symbol): // symbol "data" has not been declared yet
            node(left, NODES::EMPTY, right), symbol(std::move(symbol)){}
};

struct op_and: op{
public:
    explicit op_and(data& left, data& right): // symbol "data" has not been declared yet
            op(left, right, "&"){}
};

#endif //_OP_H
/* including "op.h" ends */

struct data: node{
    std::string name;
    int width;
};

op_and* operator&(data& left, data& right){
    return new op_and(left, right); // error
}

#endif //_DATA_H

Now, definitions of struct op, struct op_and, and method operator& are in-valid since symbol data has not been declared.
So, if I put #include "op.h" after the definition of struct node, things work fine.

#ifndef _DATA_H
#define _DATA_H

#include <string>
#include <utility>
#include "node.h"

struct data: node{
    std::string name;
    int width;
};

#include "op.h"

op_and* operator&(data& left, data& right){
    return new op_and(left, right);
}

#endif //_DATA_H
Jason
  • 36,170
  • 5
  • 26
  • 60
Kera
  • 73
  • 6
  • 2
    Circular dependency. data .h needs op.h. op.h needs data.h. Which comes first? Same again with node.h and everybody else. – user4581301 Oct 28 '22 at 02:35
  • Side note: [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/q/228783/4581301) Breaking these rules doesn't bite all that often, but when it does bite, you come away looking like the poor lady out night swimming at the beginning of Jaws. – user4581301 Oct 28 '22 at 02:41
  • I misread. There is no node.h. Wonder what I was smoking. – user4581301 Oct 28 '22 at 02:44

0 Answers0