Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template specialization without default function

People also ask

Are template specializations inline?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is the difference between generic class template and specialization template?

Key differences between generics and C++ templates: Generics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime. The common language runtime specifically supports generics in MSIL.

When we specialize a function template it is called?

To do so, we can use a function template specialization (sometimes called a full or explicit function template specialization) to create a specialized version of the print() function for type double.

What is the difference between template typename T and template T?

There is no difference. typename and class are interchangeable in the declaration of a type template parameter.


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.


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.


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);
}

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.


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);