I have the following code that compiles and works well:
template
T GetGlobal(const char *name);
template<>
int GetGlobal(cons
I would suggest not to actually provide an implementation, just a bare declaration of the method.
The other option would be to use a compile-time assert. Boost has a number of such beasts.
namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
boost::same_type<T, int> >));
There is also its message version counterpart, which would help.
Though it is an old and outdated question, it may worth noting that C++11
had solved this issue using deleted functions:
template<typename T>
T GetGlobal(const char *name) = delete;
template<>
int GetGlobal<int>(const char *name);
UPDATE
This will not compile under MacOS llvm 8
.
It is due to a still hanging 4 years old defect (see this bug report).
The following workaround will fit the issue (using a static_assert
construct).
template<typename T>
T GetGlobal(const char *name) {
static_assert(sizeof(T) == 0, "Only specializations of GetGlobal can be used");
}
template<>
int GetGlobal<int>(const char *name);
UPDATE
Visual studio 15.9 has the same bug. Use the previous workaround for it.
The following are alternative techniques to using boost:
Declare a typedef to a dependent name
This works because name lookup for DONT only occurs when 'T' has been replaced. This is a similar (but legal) version of the example given by Kirill
template <typename T>
T GetGlobal (const char * name) {
typedef typename T::DONT CALL_THIS_FUNCTION;
}
Use an incomplete return type
This technique doesn't work for specializations, but it will work for overloads. The idea is that its legal to declare a function which returns an incomplete type, but not to call it:
template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
If you don't implement it, you'll at least get a linker error. If you want a compile-time error, you could do this with class templates:
template<typename T>
struct GlobalGetter;
template<>
struct GlobalGetter<int> {
static int GetGlobal(const char *name);
};
template<>
struct GlobalGetter<double> {
static double GetGlobal(const char *name);
};
template<typename T>
T GetGlobal(const char *name)
{
return GlobalGetter<T>::GetGlobal(name);
}
To get a compile-time error implement it as:
template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined
If you use Boost you could make it more elegant:
template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
C++ Standard guarantees that there is no such type which has sizeof equal to 0, so you'll get a compile-time error.
As sbi suggested in his comments the last could be reduced to:
template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }
I prefer the first solution, because it gives more clear error message (at least in Visual C++) than the others.