Home > front end >  class field with a type defined in an anonymous namespace
class field with a type defined in an anonymous namespace

Time:03-25

I have a struct defined in an anonymous namespace. Then I also want to have a class defined which has a field of that struct type. I forward declare the struct in the header file:

struct my_str;

class my_class {
public:
  struct my_str *field;
  void method();
};

and then in the cpp file I have the actual type defined and some methods using it:

namespace {
struct my_str {
  int data;
};
}

void helper(struct my_str * obj) {
  std::cout << obj->data;
}

void my_class::method() {
  helper(field);
}

This doesn't compile:

test.cc:10:20: error: reference to ‘my_str’ is ambiguous

It lists 2 definitions for my_str, the forward declaration and the one from the anonymous namespace.
Is there a way to disambiguate and make this compile?

CodePudding user response:

An anonymous namespace hides the name from the outside, so you can't use that - there is no way for an outsider to refer to that type.

You don't need to write the definition in an anonymous namespace - it is hidden outside anyway.
However, this will lead to undefined behaviour if you have another global type with the same name, due to the One Definition Rule.

Probably the best solution is to hide the definition inside my_class instead:

Header:

class my_class {
public:
  // Note the separate declaration; a one-liner would declare 
  // that there is a global `my_str`.
  struct my_str; // Not defined for the outside world, but the name is accessible.
  my_str *field;
  void method();
};

Source:

struct my_class::my_str
{
    int data;
};

namespace
{
    void helper(my_data::my_str* obj) {
      std::cout << obj->data;
    }
}

void my_class::method() {
  helper(field);
}

CodePudding user response:

I came up with this approach and would like to hear what people think. "every problem in computer science can be solved by adding another level of indirection"

.h:

struct my_str_wrap;

class my_class {
public:
  struct my_str_wrap* field;
  void method();
};

.cc:

namespace {
struct my_str {
  int data;
};
}

struct my_str_wrap {
  struct my_str w;
};

void helper(struct my_str& obj) {
  std::cout << obj.data;
}

void  my_class::method() {
  helper(field->w);
}
  • Related