Search code examples
c++dependenciestemplate-specializationc++20

Module dependencies when using template function specializations


Please check out the following code snippet (pseudo code, didn't compile it):

A.h

template <typename T>
void SubTest(T t) = delete;

template <>
void SubTest(int i)
{
    cout << i;
}

template <typename T>
class MyClass
{
    public:
        void Test(T t)
        {
            SubTest(t);
        }
}

B.h

class X{};

template <>
void SubTest(X x)
{
    cout << x;
}

As you can see I want a class template method to call a function template. That function is specialized in various ways. Some of the specializations are located in A.h, some in other in optional headers (like B.h). I want to avoid A.h to be dependent from B.h etc. since A.h can work standalone but should be extendable by an number of other other modules providing specializations. Logically this dependency is not necessary but it seems technically it can not be avoided.

AFAIK C++ requires two conditions:

  1. All specilizations need to be declared before they are used
  2. The primary function prototype must be declared before each specialization

I could include A.h in B.h. or I could repeat template <typename T> void SubTest(T t) = delete; in B.h to fulfill condition 2. However this still wouldn't fulfill 1.

I could include B.h in the middle of A.h but that would create a (logically) unwanted dependency.

Is there a way to solve this problem at compile time in C++ up to C++20?


Solution

  • While it’s true that specializations “need to be declared before they are used”, that doesn’t mean before their caller is defined, but before it is instantiated so as to use the specialization in question. This is critical to any customization scheme: you define the base case, then clients #include that and define specializations for their classes immediately after their definitions. Further clients necessarily have the specializations available if they have the classes available, so everything works. None of this has changed since C++98.

    (Meanwhile, you can’t repeat =delete for a function: that counts as a definition, and must appear on the first declaration as well.)