强制实例化所有模板 类 成员函数
Forcing instantiation of all of a template classes member functions
在模板 class 的初始开发过程中,在我编写完整的测试用例之前,我发现我希望能够强制编译器为每个成员(包括非静态的)模板 class 用于一组特定的模板参数,只是为了确保所有代码至少编译。
具体来说,我正在使用 GCC 9(对于其他编译器我真的不需要这种能力,因为它只是我想在开发过程中临时实现的东西);及其 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...
};
而且,鉴于我事先知道有限的可能模板参数集(假设这里是 int
和 float
),我只是想确保它们至少在我编译时编译我在工作。
现在我可以做到这一点,这显然是不够的:
int main () {
test_me<int> i;
test_me<float> f;
}
由于未生成 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>();
}
但这会变得很痛苦,尤其是当成员函数开始具有复杂的副作用或前提条件,或者需要重要参数,或者具有非 public 成员和尚未开发的朋友时。所以,我想要一种测试编译而不必显式调用所有内容的方法(并且,理想情况下,我希望能够在不修改任何“测试”代码的情况下测试编译 当我添加新成员时)。
所以我的问题是:至少 GCC 9,[=41=]有没有办法强制(可能是暂时的)编译器为模板 class 的整个成员集生成代码, 给定模板参数?
语言不允许您尝试执行的操作,至少对于您的测试的隐式实例化 class。当您使用某种类型隐式实例化 test_me
时,不允许隐式实例化成员函数的定义,根据 temp.inst#11:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
因此,如果您想隐式实例化所有 mistake
成员函数,您别无选择,只能以某种方式要求它们实例化。正如您使用 testCalls
的示例,您可以调用这些成员函数,或者您可以 ODR 以其他方式使用它们,例如获取它们的地址。
只需显式实例化class:
template struct test_me<int>;
template struct test_me<float>;
在模板 class 的初始开发过程中,在我编写完整的测试用例之前,我发现我希望能够强制编译器为每个成员(包括非静态的)模板 class 用于一组特定的模板参数,只是为了确保所有代码至少编译。
具体来说,我正在使用 GCC 9(对于其他编译器我真的不需要这种能力,因为它只是我想在开发过程中临时实现的东西);及其 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...
};
而且,鉴于我事先知道有限的可能模板参数集(假设这里是 int
和 float
),我只是想确保它们至少在我编译时编译我在工作。
现在我可以做到这一点,这显然是不够的:
int main () {
test_me<int> i;
test_me<float> f;
}
由于未生成 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>();
}
但这会变得很痛苦,尤其是当成员函数开始具有复杂的副作用或前提条件,或者需要重要参数,或者具有非 public 成员和尚未开发的朋友时。所以,我想要一种测试编译而不必显式调用所有内容的方法(并且,理想情况下,我希望能够在不修改任何“测试”代码的情况下测试编译 当我添加新成员时)。
所以我的问题是:至少 GCC 9,[=41=]有没有办法强制(可能是暂时的)编译器为模板 class 的整个成员集生成代码, 给定模板参数?
语言不允许您尝试执行的操作,至少对于您的测试的隐式实例化 class。当您使用某种类型隐式实例化 test_me
时,不允许隐式实例化成员函数的定义,根据 temp.inst#11:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
因此,如果您想隐式实例化所有 mistake
成员函数,您别无选择,只能以某种方式要求它们实例化。正如您使用 testCalls
的示例,您可以调用这些成员函数,或者您可以 ODR 以其他方式使用它们,例如获取它们的地址。
只需显式实例化class:
template struct test_me<int>;
template struct test_me<float>;