Reputation: 17197
If I have a template class MyClass<T>
and if I explicitly instantiate for int
and float
(in a cpp
file) then I can use extern template class MyClass<int>
and extern template class MyClass<float>
to prevent any compilation unit encountering this class from instantiating it for int
and float
unnecessarily. Of course, for any other type, the class will still get instantiated.
Now I have a class MyClass2<T>
which only works with int
, float
, char
, double
, short
and their unsigned variants where applicable. Since I know all the types beforehand, the definitions of all the methods in this class are in the cpp
file. This is also where I explicitly instantiate MyClass2<T>
for all the above mentioned types. In the header, I have static_assert
preventing the user from creating MyClass2<T>
with an unsupported type.
Is there any way to completely prevent MyClass2<T>
from instantiating (e.g. extern template class MyClass2;
although I know that doesn't work) for all types including supported types? Like a catch all for extern template
? I want to avoid typing out extern template class MyClass2<int>
for all the supported types.
Considering I have already explicitly instantiated the class for those types, it seems not only redundant but for big projects (like the one I am working on) yet another few lines that I need to maintain each time a new type is added.
Upvotes: 1
Views: 463
Reputation: 137310
This honestly sounds like the job for a macro:
// explicit_instantiations.h
#ifndef PERFORM_INSTANTIANTION
#define EXTERNALLY_INSTANTIATED extern
#else
#define EXTERNALLY_INSTANTIATED
#endif
EXTERNALLY_INSTANTIATED template class MyClass<int>;
EXTERNALLY_INSTANTIATED template class MyClass<float>;
// etc.
// header
#include "explicit_instantiations.h"
// cpp file
#define PERFORM_INSTANTIATION
#include "explicit_instantiations.h"
Upvotes: 1
Reputation: 47784
You can use SFINAE something like following
template<typename T>
using value_type = typename std::enable_if<
std::is_same<float, T>::value ||
std::is_same<double, T>::value
//...other supported types goes here
>::type ;
template<class T, class Enable = void>
class MyClass2 ;
template<class T>
class MyClass2<T, value_type<T> >
{
};
MyClass2<float> t;
MyClass2<int> t1; // Error !
See Here
Upvotes: 2
Reputation:
What about:
template <typename T>
struct Base {};
template <typename T>
struct Supported;
template <>
struct Supported<int> : public Base<int>
{};
Upvotes: 0