3

So far, I had a setup where a certain function template getF was declared like this in the headers

template <typename T> F* getF();

leaving the function body undefined. Then on a shared library, getFhas some specializations..

template<>
F* getF<int>()
{
  static int r = 42;
  static Finstance(r);
  return &Finstance;
}

template<>
F* getF<float>()
{
  static float r = 3.14159;
  static Finstance(r);
  return &Finstance;
}

The above has work so far nicely, as when on a client executable I invoke getF<float>(), the linker will replace with the appropriate references, and if the specialization doesn't exist in the library, then the compilation will fail with a linker error (which was the desired behavior)

However, Now there should be a small change in the behavior: when the result is not specialized for a given template parameter, the code should build, but return 0 at run-time. So what I did is change the declaration of getF like this:

template <typename T> F* getF() { return 0; }

The problem is that, now the compiler will use this definition for all cases, regardless if there is an specialization in the library

Question: Is there some other way to provide some default behaviour for the function at runtime, without moving the specializations to header files?

lurscher
  • 25,930
  • 29
  • 122
  • 185
  • 1
    You can declare the specializations in the header, but only define them in the library. Other than that, I'm pretty sure this can't be done (without, say a custom linker or something). – Mankarse Jun 22 '14 at 23:58

2 Answers2

4

The best solution is to declare that the library's explicit specializations exist.

// All in the same header file:
template <typename T> F* getF() { return 0; }
template <> F* getF<int>();
template <> F* getF<float>();

This satisfies the rule from Standard 14.7.3/6:

If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

aschepler
  • 70,891
  • 9
  • 107
  • 161
0

Essentially you want the following: "enable special cases of F when T is int or float". It is exactly what constructs like boost::enable_if and std::enable_if are about.

There are subtle differences in enabling/disabling functions vs. classes (classes are easier). See good examples here: boost::enable_if not in function signature

You might need some MPL (Boost Meta-programming Library) to express the "or" part of your rule.

Community
  • 1
  • 1
Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24