I coded a message queue template in c++, and I want use it in many different projects, so that I put it into a namespace, for example my_lib
.
In order to prevent the codes from being compiled repeatedly, I used a separate trans-unit to explicitly instantiate it (and get only one obj file), and merely include its header every where involving it.
But where it being used, is in another namespace for example business
.
The skeleton of my codes looks like the followings:
mq-template.hpp:
#pragma once
namespace my_lib {
template<typename T, typename SIZE_TYPE>
class GenericMQ_t {
struct Node_t {
SIZE_TYPE _head;
SIZE_TYPE _tail;
T _data;
};
SIZE_TYPE _size {};
Node_t* _buff {};
public:
void send( const T& );
};
}; // namespace my_lib
mq-template.tpp (mind the suffix):
#include "mq-template.hpp"
namespace my_lib {
template<typename T, typename SIZE_TYPE>
void GenericMQ_t<T, SIZE_TYPE>::send( const T& ) {
// just for example
std::cout << "Hello!";
};
}; // namespace my_lib
mq-instance.hpp:
#pragma once
#include "mq-template.hpp"
namespace business {
struct Msg_t {};
using RealMQ_t = my_lib::GenericMQ_t<Msg_t, int>;
}; // namespace business
mq-instance.cpp:
#include "mq-instance.hpp"
#include "mq-template.tpp"
namespace business {
template class my_lib::GenericMQ_t<Msg_t, int>;
}; // namespace business
main.cpp:
#include "mq-instance.hpp"
int main() {
business::Msg_t msg;
business::RealMQ_t mq;
mq.send( msg );
return 0;
}
When mq-instance.cpp
was compiling, I got some error like this:
explicit instantiation of 'class my_lib::GenericMQ_t<business::Msg_t, int>' in namespace 'business' (which does not enclose namespace 'my_lib') [-fpermissive]
explicit instantiation of 'struct my_lib::GenericMQ_t<business::Msg_t, int>::Node_t' in namespace 'business' (which does not enclose namespace 'my_lib') [-fpermissive]
It is impossible to put my all codes into a same namespace, because they belongs to different projects, and even though in a same project, the naming schema may be hierarchical.
How should I modify my code, let it satisfy both of:
You can move the explicit instantiation to the enclosing namespace(which is global namespace) as shown below.
mq-instance.cpp
#include "mq-instance.hpp"
#include "mq-template.tpp"
template class my_lib::GenericMQ_t<business::Msg_t, int>; //in global namespace
namespace business {
};