3

See the code below:

#include <iostream>

/// Definition of void perform(a_lib::a_class&). Where should I put this definition?
/// See the comments below for where I've tried placing it.
// void perform(a_lib::a_class&) {
//   std::cout << "performing on a_lib::a_class" << std::endl;
// }

namespace a_lib {
  class a_class {  };

  // WORKS HERE but it pollutes a_lib (namespace of third-party library).
}

namespace mine {
  // DOESN'T WORK HERE: "use of undeclared identifier 'perform'".
}

// WORKS HERE but it pollutes the global namespace.

namespace b_lib {
  // WORKS HERE but it pollutes b_lib (namespace of third-party library).

  template <typename Type>
  void b_func(Type& obj) {
    perform(obj);
  }
}

namespace mine {
  // DOESN'T WORK HERE: "use of undeclared identifier 'perform'".

  void run() {
    a_lib::a_class a_obj;
    b_lib::b_func(a_obj);
  }
}

int main(int, char**) {
  mine::run();

  return 0;
}

a_lib and b_lib are namespaces belonging to two different third-party libraries. mine is my own namespace.

I've been taught that it's a bad idea to pollute the global namespace and in this question they also say that adding types to std is a bad idea. I'm thinking the latter is true for namespaces in general; you should not add types to a namespace that's not yours.

But how I would I solve the problem above without breaking these principles? Where should I put the definition of perform() and how can I get b_func() to call it?

Context: I'm trying to add an external cereal serialize() for a SFML type in my own namespace. This here is a reduced example.

haisareisa
  • 33
  • 4
  • To extend the interface of `a_lib::a_class` you should add things to that type's namespace. Whether it's a good idea to extend the interface of types you don't own (e.g. by making them serializable) is the key question, but if you are going to do that then you should do it in the type's namespace. Another option is to define your own type that derives from `a_class`, in your own namespace, and add the serialization support in your namespace. – Jonathan Wakely Apr 04 '16 at 11:49
  • *"Whether it's a good idea to extend the interface of types you don't own (e.g. by making them serializable) is the key question"* That's a really good point. I'll derive from `a_class` instead. Thank you. – haisareisa Apr 04 '16 at 15:07

1 Answers1

0

You need to identify where the compiler, when processing "b_func" can find the "perform".

namespace mine {
  // DOESN'T WORK HERE: "use of undeclared identifier 'perform'".

  // dom -  yes it will, but there is 'more' to the name than your example shows

  void perform(Type& obj) { /* do something with obj */}

}

// WORKS HERE but it pollutes the global namespace.

namespace b_lib {
  // WORKS HERE but it pollutes b_lib (namespace of third-party library).

  // dom -  use here is easy with correct and 'more-complete' name:

  template <typename Type>
  void b_func(Type& obj) {  mine::perform(obj); }
  // -----------------------^^^^^^^^^^^^^^^^^^^ --- more to name
}

Since "mine" is a namespace, a more complete name can 'reach across' the name spaces.

Note that at mine::perform() implementation, "Type" must also be defined to use the obj.

2785528
  • 5,438
  • 2
  • 18
  • 20
  • 1
    If I understood you correctly you're suggesting that I edit the definition of `b_func()`. The problem is that it's part of a third-party library and I therefore shouldn't edit its definition. – haisareisa Apr 04 '16 at 12:14
  • If you can not modify b_func, then b_func() must currently invoke a "perform()" method / function that already exists. The name suggests "perform" is already in global, and thus can not add more 'pollution'. – 2785528 Apr 04 '16 at 12:26
  • No it doesn't suggest that. Presumably it calls the function unqualified in order for it to be found by ADL, in order to find a function defined in the associated namespaces of `a_lib::a_class`. – Jonathan Wakely Apr 04 '16 at 15:33
  • Sorry, I have not heard of ADL, unable to find it. – 2785528 Apr 04 '16 at 18:54