C++ 模板继承中强制的完整模板实例化?

Full template instantiation forced in C++ template inheritance?

我们都知道C++ class模板不会生成不用的成员函数,如下图:

template<typename T>
class A
{
    public:
    void WrongFunction(T t);
    void RightFunction(T t);
};

template<typename T>
void A<T>::WrongFunction(T t)
{
    std::vector<T> v;
    auto a = "abc" - v;
}

template<typename T>
void A<T>::RightFunction(T t)
{
    std::cout << "Success" << std::endl;
}

int main()
{
    A<int> a;
    a.RightFunction(2);
    //a.WrongFunction(1);
    return 0;
}

由于在 main 中没有调用 WrongFunction,因此没有为其生成实际代码,因此不会发生编译错误。

现在,让我们介绍一个抽象基础 class,它定义了 class A(基本上是模板继承)的接口:

template<typename T>
class Base
{
    public:
    virtual void RightFunction(T t) = 0;
    virtual void WrongFunction(T t) = 0;
};

template<typename T>
class A : Base<T>
{
    public:
    void WrongFunction(T t) override;
    void RightFunction(T t) override;
};

template<typename T>
void A<T>::WrongFunction(T t)
{
    std::vector<T> v;
    auto a = "abc" - v;
}

template<typename T>
void A<T>::RightFunction(T t)
{
    std::cout << "Success" << std::endl;
}

int main()
{
    A<int> a;
    a.RightFunction(2);
    //a.WrongFunction(1);
    return 0;
}

编译器突然拒绝工作:

prog.cc: In instantiation of 'void A::WrongFunction(T) [with T = int]': prog.cc:39:1: required from here prog.cc:24:20: error: no match for 'operator-' (operand types are 'const char [4]' and 'std::vector >') auto a = "abc" - v;

我对工作流程的理解是,主要是,我说创建一个A的实例。好的,编译器然后找到A的模板声明(注意A不是class; A<SomeType> 是。)。哇,这取决于Base<int>。很好,然后编译器找到 Base 的模板声明,将 int 插入到 T 所在的位置 - 现在我们有 class Base<int> 的声明,但没有生成定义 - 毕竟,我们做了没有为 Base<SomeType> 提供定义生成模板,并且没有人创建过 Base<int> 的任何实例或调用过该实例的函数。没关系。然后编译器扩展 Base<int> 的声明并生成 A<int> 的声明。等等,在下一行,调用了 RightFunction。所以编译器找到A的RightFunction的模板定义并插入特定类型的int并生成A的成员函数定义。

因为从未调用 WrongFunction(也没有涉及专门化;也没有显式实例化),编译器甚至不应该尝试为 A<int>::WrongFunction 生成代码 ---我的问题是,这到底是怎么回事?

编译器:gcc 4.9.2

谢谢。

来自 N3337,§14.7.1/10 [temp.inst]

An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated. ...

因此,实现实例化虚拟成员函数是合法的,即使您从未调用过它。

在实践中,这很可能总是如此,因为在实例化一个 class 模板时,编译器还需要为那个 class 实例化 vtable,它必须填充虚拟地址成员函数。