Search code examples
c++templatescompilationconditional-compilationspecialization

Prevent compilation of unused template specialization in c++


Let's consider a struct Foo, templated by an enum called TYPE:

enum TYPE
{
    TYPE_A,
    TYPE_B
};

template<TYPE T>
struct Foo;

Foo is not defined but only specialized twice. One specialization adds a int* to the class while the other adds a pointer to an object of type MayBeNotDefined:

template<>
struct Foo<TYPE_A>
{
    int* A;
};

template<>
struct Foo<TYPE_B>
{
    MayBeNotDefined* B;
};

The MayBeNotDefined type is not defined in some of my project, so only Foo<TYPE_A> is used:

int main()
{
    Foo<TYPE_A> a;
    a.A = new int;
    //...
}

In other projects, MayBeNotDefined is actually defined before the declaration of Foo (with something like using MayBeNotDefined = int;) and both Foo<TYPE_A> and Foo<TYPE_B> are used:

int main()
{
    Foo<TYPE_A> a;
    Foo<TYPE_B> b;
    //...
}

The thing is that in the first case, the compiler generates code for both specializations, even if I only use Foo<TYPE_A>... Therefore, an error occurs since MayBeNotDefined is unknown.

So I have two questions :

  • Why does the compiler need to generate code for every specializations? I naively thought that if the compiler meets a variable of type Foo<TYPE_A>, then it would generate only the code of the first specialization. If no Foo<TYPE_B> are parsed, why does it need to also generate the associated code?

  • How to prevent the compiler to compile code for unused specialization? Is there any easy workaround, preferably without using pre-processor macros? It seems possible to 'delete' already compiled but unused code (cf G++ generates code for unused template specializations?). What I want is that the code is not even compiled at all, so that the undefined type MayBeNotDefined is not a problem.

Thanks!


Solution

  • Why does the compiler need to generate code for every specializations?

    The compiler doesn't need to generate code for unused template specialization, but it must ensure it's definition is correct according to the same rules as those applied to generic classes.

    How to prevent the compiler to compile code for unused specialization?

    You cannot. Unused specializations must compile, but if they do, the (decent) compiler won't produce binary code for it.

    But, if you told us what you exactly expect, we might give you alternative. As example:

    enum TYPE
    {
        TYPE_A,
        TYPE_B
    };
    
    
    template<TYPE T>
    struct MayBeNotDefined;
    
    
    // FOR PROJECT WITH MayBeNotDefined ONLY ---
    template<>
    struct MayBeNotDefined<TYPE_B> { typedef char type; };
    // FOR PROJECT WITH MayBeNotDefined ONLY ---
    
    template<TYPE T>
    struct Foo
    {
        typename MayBeNotDefined<T>::type* B;
    };
    
    template<>
    struct Foo<TYPE_A>
    {
        int* A;
    };
    
    
    int main()
    {
        Foo<TYPE_A> a;
        a.A = new int;
    
        // FOR PROJECT WITH MayBeNotDefined ONLY ---
        Foo<TYPE_B> b;
        b.B = new char;
        // FOR PROJECT WITH MayBeNotDefined ONLY ---
    }
    

    (this works even if you remove the two specified blocks)