防止在c ++中编译未使用的模板特化

时间:2017-12-05 13:19:10

标签: c++ templates compilation conditional-compilation specialization

让我们考虑一个结构Foo,由名为TYPE的枚举模板化:

enum TYPE
{
    TYPE_A,
    TYPE_B
};

template<TYPE T>
struct Foo;

Foo未定义,但只有两次专门定义。一个专门化为类添加int*,而另一个专门化添加指向MayBeNotDefined类型的对象的指针:

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

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

我的某些项目中未定义MayBeNotDefined类型,因此仅使用Foo<TYPE_A>

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

在其他项目中,MayBeNotDefined实际上是在Foo声明之前定义的(类似using MayBeNotDefined = int;),Foo<TYPE_A>Foo<TYPE_B>都使用了:

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

问题在于,在第一种情况下,编译器为两个特化都生成代码,即使我只使用Foo<TYPE_A> ...因此,由于MayBeNotDefined未知,所以会发生错误。

所以我有两个问题:

  • 为什么编译器需要为每个专业化生成代码? 我天真地认为,如果编译器遇到Foo<TYPE_A>类型的变量,那么它只会生成第一个特化的代码。如果没有解析Foo<TYPE_B>,为什么还需要生成相关代码?

  • 如何防止编译器为未使用的专业化编译代码?有没有简单的解决方法,最好不使用预处理器宏?似乎可以删除&#39;已编译但未使用的代码( cf G++ generates code for unused template specializations?)。我想要的是根本没有编译代码,因此未定义的类型MayBeNotDefined不是问题。

谢谢!

1 个答案:

答案 0 :(得分:1)

  

为什么编译器需要为每个特化生成代码?

编译器不需要为未使用的模板专门化生成代码,但必须根据与应用于泛型类的规则相同的规则来确保它的定义是正确的。

  

如何防止编译器编译未使用的专业化代码?

你做不到。未使用的专业化必须编译,但如果他们这样做,(体面的)编译器不会为它生成二进制代码。

但是,如果你告诉我们你的期望,我们可能会给你另类。例如:

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

(即使删除了两个指定的块也可以使用)