I'm building an extensible "type system" in C++ that, amongst other things, needs to map C++ float types to my "wobbly types". The mechanism I've devised for this is to construct a helper struct, templated by the concrete C++ type, that has a single static function get_type
that returns a pointer to my type:
template <typename T> struct type_helper {
static const my_type* get_type();
};
Now the common types like float
and double
have a specialization of this struct, and the corresponding get_type
method is defined in a cpp file:
// in types.h
template <> const my_type* type_helper<float>::get_type();
// in float_type.cpp
#include "types.h"
template <> const my_type* type_helper<float>::get_type() {
static const float_type ftype;
return &ftype;
}
Note that the definition of float_type
is not externally visible, and nor should it be.
This works great inside the shared library in which these objects are commonly defined, but I need the symbols to be visible outside for the other components of the library to find. Using the standard design, I've got a macro EXPORT_SYMBOL
that is replaced by __attribute__((visiblity('default'))
on GCC (for example) that I use to make symbols linkable. However, simply adding this attribute to the specialized declarations doesn't seem to have the desired effect, and neither does adding it to the primary template. (E.g.
template <> EXPORT_SYMBOL const my_type* type_helper<float>::get_type();
It seems to me that the "correct" strategy for this particular problem is to declare an extern template
specialization of the primary template but, to my knowledge, that doesn't allow for specializing definition of individual member functions. What is the "correct" way to solve this problem?
I want to add that this is for the other library components and not the "user facing" part of the interface. For them, there is a type registration system and a separate retrieval function (with no templates, using a type id string) that all works fine.