Using an externally defined class within a namespace

Lets say I have a library which declares all of its classes / types in a namespace. I would like to create a class which utilizes one of these namespaced classes / types as a data member, without including the header file where this namespaced class / type is defined.

So something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// library_header.h
namespace ThisNamespace
{
  class DataType
  {
    ...
  };
};

// myClass.h
class ThisNamespace::DataType;
typedef ThisNamespace::DataType Handle;

class MyClass
{
  Handle m_Handle;
  ...
};

// myClass.cpp
#include "library_header.h"

...

However, this obviously will not compile, and produces an error with regards to redefinition of the namespace ThisNamespace in the myClass.h file. Considering that if DataType was not in a namespace the line "class DataType;" would compile, is there a way to get this to work?

why don't you just include the libs header?
I am compiling the MyClass data structure into a lib of its own (in actually it will probably be hundreds of structures), and I would like the headers to be independent of any libraries which they might depend on. Specifically, I am thinking in regards to boost function binds - I would like my main.cpp file to be oblivious to the fact that the lib is using boost.
So something like
1
2
3
4
// myClass.h
namespace ThisNamespace {
    class Datatype;
}

fails?
Yep, that gives me "m_Handle uses undefined class 'ThisNamespace::DataType' " and "redefinition; different basic types of ThisNamespace::DataType" with VS 10.
Never had similar trouble.

Try something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// !!!! library_header.h !!!!

namespace ThisNamespace {
    class Datatype;
   /* Here, define all classes in your library...
    * Like, you gonna create another class called FOO?
    * Put it here!
    */
    class FOO;
    class AnotherClass;
};
#include "myClass.h"
#include "FOO.h" // Include all headers of the classes you defined
#include "AnotherClass.h"

// End of library_header.h

// !!!! myClass.h !!!!

namespace ThisNamespace {
    class Datatype {
        // ...
    };
};

// End of myClass.h

// !!!! myClass.cpp !!!!

//!!!! DO NOT INCLUDE LIBRARY_HEADER.H FROM HERE! !!!!
namespace ThisNamespace {
    Datatype:://... The function definitions
};

// End of myClass.cpp 


Then, from your main.cpp...

1
2
#include "library_header.h"
// Your code... 
The problem is that you are not using include guards.
The problem is that you want an object but never provided its definition.
Forward declaration is to use with pointers and references, by instance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// myClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H
namespace ThisNamespace{
   class DataType;
}
typedef ThisNamespace::DataType* Handle;

class MyClass
{
   Handle m_Handle;
   //...
};

#endif 

Never had similar trouble.

Try something like:
...


I do not have the option of changing what is in the "library_header.h" file (short of recompiling the entire library), so I do not think that solution will work in this case.


The problem is that you are not using include guards.
The problem is that you want an object but never provided its definition.
Forward declaration is to use with pointers and references, by instance


Making the typedef a pointer did solve part of the problem, however I still get the redefinition of ThisNamespace::DataType. Also what may potentially add more complexity to the problem is that in the example that I am working with DataType is declared as a typedef of a typedef of a typedef of a struct.

I have been able to get this to work in the past using a wrapper struct around ThisNamespace::DataType below the #include "library_header.h", however I am hoping that there is a more elegant solution.
Are you forced to have both a include and a source file for myClass? It looks like you only need the Source file, as, you cannot edit library_header.h and library_header.h contains the definition. Just put the declaration in myClass.cpp and remove myClass.h and see if it works.

Are you forced to have both a include and a source file for myClass? It looks like you only need the Source file, as, you cannot edit library_header.h and library_header.h contains the definition. Just put the declaration in myClass.cpp and remove myClass.h and see if it works.


In some cases I will need both, in other cases I will need only the header file. Other classes will need to know what methods MyClass has (specifically the constructor), and in a few situations, the an interface class will have a virtual function that will need to take an argument of Handle. I do not think declaring everything in the myClass.cpp file will work here.
however I still get the redefinition of ThisNamespace::DataType
¿did you put the guards?

¿did you put the guards?


I am using #pragma once, which should be equivelant to the #ifdef guards. I think the problem is that the compiler is seeing the declaration in the myClass.h file as the definition, and the actual declaration in the library_header.h file as the redefinition.
So remove temporarily myclass.h, and check if it works. Also don't trust much #pragma once.
#ifndef/#define/#endif are safer.
A forward declaration is not a definition, so it shouldn't happen
Post the updated code.
The solution that ne555 posted works if it is an externally defined class:
1
2
3
4
namespace ThisNamespace{
   class DataType;
}
typedef ThisNamespace::DataType* Handle;


I was unable to validate that solution as I was testing it on one of the actual cases that I was interested in - which defines the type through typedef. So I guess the question right now is, what if my code looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// library_header.h
namespace ThisNamespace
{
  namespace NewNamespace
  {
       template<typename T1, typename T2>
       class DataType
       {
         ...
       };
  }

  typedef NewNamespace::DataType<float,int> DataType2;

};

// myClass.h
namespace ThisNamespace
{
   class DataType2;
};

typedef ThisNamespace::DataType2* Handle;

class MyClass
{
  Handle m_Handle;
  ...
};

// myClass.cpp
#include "library_header.h"

...

(the above code has not shown the include guards for brevity)
This case does not compile, and is closer to what I am actually working with. Is there a way to get this to work?
1
2
3
4
5
6
7
8
9
10
11
12
//somehow in myClass.h
namespace ThisNamespace
{
   namespace NewNamespace
   {
      template<typename T1, typename T2>
      class DataType;
   }

   typedef NewNamespace::DataType<float,int> DataType2;

};
Topic archived. No new replies allowed.