C++ 强制实例化所有模板类成员函数

C++ 强制实例化所有模板类成员函数,c++,templates,testing,gcc,gcc9,C++,Templates,Testing,Gcc,Gcc9,在模板类的初始开发过程中,在编写完整的测试用例之前,我发现我希望能够强制编译器为模板类的每个成员(包括非静态成员)为一组特定的模板参数生成代码,以确保所有代码至少都能编译 具体来说,我使用的是GCC9(对于其他编译器,我并不真正需要这种能力,因为这只是我想在开发过程中暂时实现的功能);及其c++14、c++17、c++2a和c++20标准 例如,我可以编写以下代码: template <typename D> struct test_me { D value; void mi

在模板类的初始开发过程中,在编写完整的测试用例之前,我发现我希望能够强制编译器为模板类的每个成员(包括非静态成员)为一组特定的模板参数生成代码,以确保所有代码至少都能编译

具体来说,我使用的是GCC9(对于其他编译器,我并不真正需要这种能力,因为这只是我想在开发过程中暂时实现的功能);及其
c++14
c++17
c++2a
c++20
标准

例如,我可以编写以下代码:

template <typename D> struct test_me {
  D value;
  void mistake1 () { value[0] = 0; }
  void mistake2 () { mistake1(value); }
  // and a bajillion other member functions...
};
由于未生成
mistake1
mistake2
,因此尽管尝试对非数组类型进行索引访问,并且函数调用不正确,代码仍能正常编译

所以我在开发过程中所做的只是编写调用所有成员函数的代码:

template <typename D> static void testCalls () {
    test_me<D> t;
    t.mistake1();
    t.mistake2();
    // and so on... so many mistakes...
}

int main () {
   testCalls<int>();
   testCalls<float>();
}
模板静态无效测试调用(){
测试时间;
t、 错误1();
t、 错误2();
//等等…这么多的错误。。。
}
int main(){
testCalls();
testCalls();
}
但这会让人感到痛苦,尤其是当成员函数开始有复杂的副作用或先决条件,或者需要非平凡的参数,或者有非公共成员和尚未开发的朋友时。因此,我想要一种不必显式调用所有内容就可以测试编译的方法(理想情况下,在添加新成员时,我希望能够在不修改任何“测试”代码的情况下测试编译)


因此,我的问题是:至少使用GCC 9,有没有一种方法可以强制(可能暂时)编译器为给定模板参数的模板类的整个成员集生成代码?

语言不允许您尝试执行的操作,至少对于测试类的隐式实例化是如此。当您使用某种类型隐式实例化
test\u me
时,不允许隐式实例化成员函数的定义,如下所示:

除非需要实例化,否则实现不应隐式实例化函数模板、变量模板、成员模板、非虚拟成员函数、模板化类的成员类或静态数据成员,或constexpr if语句([stmt.if])的子状态


因此,如果您想隐式实例化所有
error
成员函数,您别无选择,只能以某种方式要求实例化它们。正如您在
testCalls
示例中所示,您可以调用这些成员函数,也可以以其他方式使用它们,例如获取它们的地址。

语言不允许您尝试执行的操作,至少对于测试类的隐式实例化是如此。当您使用某种类型隐式实例化
test\u me
时,不允许隐式实例化成员函数的定义,如下所示:

除非需要实例化,否则实现不应隐式实例化函数模板、变量模板、成员模板、非虚拟成员函数、模板化类的成员类或静态数据成员,或constexpr if语句([stmt.if])的子状态


因此,如果您想隐式实例化所有
error
成员函数,您别无选择,只能以某种方式要求实例化它们。与您的示例中的
testCalls
一样,您可以调用这些成员函数,也可以以其他方式使用它们,例如获取它们的地址。

只需显式地实例化类:

template struct test_me<int>;
template struct test_me<float>;
模板结构测试;
模板结构测试;

只需显式地
实例化类:

template struct test_me<int>;
template struct test_me<float>;
模板结构测试;
模板结构测试;

为它们声明一组(成员)函数指针,并实例化它们。为函数编写单元测试。如果你没有,你不应该在第一个地方的功能。将其与函数一起编写。@JasonC好的想法是为
T
声明一个类型特征类,您可以在某个点使用
static\u assert
s的数量进行检查。这将使错误消息更具可读性,即使没有其他代码尝试实例化该函数,您也可以指出
T
中缺少的内容。反射和具体化将使这成为可能。@JasonC为它们声明一组(成员)函数指针,并实例化它们。为您的函数编写一个单元测试。如果你没有,你不应该在第一个地方的功能。将其与函数一起编写。@JasonC好的想法是为
T
声明一个类型特征类,您可以在某个点使用
static\u assert
s的数量进行检查。这将使错误消息更具可读性,即使没有其他代码尝试实例化该函数,您也可以指出
T
中缺少的内容。反射和具体化将使这成为可能。@JasonC Darn。再清楚不过了。谢谢你把它拉上来。获取地址似乎是一个不错的选择()。@JasonC是的,这似乎很不幸,但实际上有很好的理由来解释这个限制(功能?)。是的,我认为获取它们的地址是表示希望实例化这些成员函数的一种很好的方式。再清楚不过了。谢谢你把它拉上来。获取地址似乎是一个不错的选择()。@JasonC是的,这似乎很不幸,但实际上有很好的理由来解释这个限制(功能?)。是的,我认为获取它们的地址是一种很好的表达方式,表示您希望实例化这些成员函数。啊!我怀疑这件事很简单