9

这个问题正在考虑模板类的显式实例化。

考虑B<T>从另一个模板类派生的模板类A<T>。我想显式实例B<T>化,因为它的方法是从动态链接中调用的,所以这些方法必须实例化,尽管它们没有在代码本身中调用。当然,继承自的方法A<T>也会被调用,所以它们也必须被实例化。

似乎 C++ 在显式实例化模板类时不会实例化基类,如以下问题所述: Do Explicit Instantiations of C++ Class Templates Instantiate Dependent Base Classes? 例子:

template<typename T>
class A{ void foo(){...} };

template<typename T>
class B : public A<T> {}

template class B<int>; // This will NOT instanciate A<int>::foo()!!!

当然,我还需要实例化所有基类。但是,我不想给客户端代码增加负担,因为类层次结构可能非常深。考虑一个包含 10 个或更多模板类的类层次结构。不应敦促客户编写 10 个显式模板实例。这不仅是大量的写​​作;当我对类层次结构进行更改时,它也会中断。

相反,我想以某种方式实现,无论何时B<T>被实例化,它的所有基类也是如此。我尝试简单地在 B 本身中实例化基类,如下所示:

template<typename T>
class B : public A<T> {
    template class A<T>; // Does not compile!
}

但这不会编译。还有其他方法可以实现吗?

4

1 回答 1

2

也许不优雅但至少可行:提供一个宏来实例化模板并要求用户使用宏而不是手动实例化:

// in A.hpp
#define INSTANTIATE_A(T) template class A<T>;

// in B.hpp
#define INSTANTIATE_B(T) \
    INSTANTIATE_A(T)     \
    template class B<T>;

如果您更喜欢“污染”类接口而不是强制使用实例化宏:添加一个protected调用模板的所有其他成员函数和基类中的版本的成员。例子:

template<typename T>
class A
{
    void foo() {...}
protected:
    void instantiate() { foo(); }
};

template<typename T>
class B : public A<T>
{
    void bar() {...}
protected:
    void instantiate() { A<T>::instantiate(); bar(); }
};

template class B<int>; // Now works as expected

更新:

第二种解决方案的替代方案:获取所有成员的函数指针并将它们保存到临时变量中:

template<typename T>
class A
{
    void foo() {...}
protected:
    void instantiate() { void (A::*p)() = &A::foo; }
};

template<typename T>
class B : public A<T>
{
    void bar() {...}
protected:
    void instantiate() { A<T>::instantiate(); void (B::*p)() = &B::foo; }
};
于 2014-05-20T09:58:01.563 回答