在我正在编写的图书馆中,我有一堂课:
template<typename T>
class my_class {};
和一个功能:
template<typename T>
void my_function(...) {};
我想保证我的代码的用户my_function<T>
在尝试实例化my_class<T>
. 换句话说,如果他们尝试实例化my_class
模板而不实例化相应的my_function
模板,我想生成一个编译错误。
例子:
int main() {
my_func<int>() // cause instantiation of my_func<int>
my_class<int> foo; // okay, because my_func<int> exists
my_class<char> bar; // compile error! my_func<char> does not exist
}
请注意,my_class<T>
不需要在my_func<T>
内部使用,因此实例化它不会自动导致my_func<T>
实例化。
编辑[0]:我不能给my_func<T>
自己打电话,因为我需要用户调用它并传递告诉库如何处理的信息my_class<T>
。IE。如果他们想使用 a my_class<char>
,他们需要在代码中的特定位置明确说明。我可以让my_class<T>
构造函数测试是否my_func<T>
已被调用,如果没有,则生成运行时错误,但我更希望能够生成编译时错误,因为在编译时可以知道是否my_func<T>
曾经使用过。
编辑[1]:一种不太理想的方法是制作一个MY_FUNC
宏来创建一个不完整的模板类的模板特化......
template<typename T>
class incomplete;
#define MY_FUNC(T) template<> incomplete<T> { static const bool x = my_func<T>(); };
template<typename T>
class my_class {
template<size_t i>
class empty {};
typedef empty<sizeof(incomplete<T>)> break_everything;
}
现在用户只能在某处使用my_class<T>
if 。MY_FUNC(T)
但是,我更喜欢不使用宏并且不强制用户MY_FUNC
在全局范围内使用而不是在函数中使用的解决方案。
编辑[2]:感谢大家的回答。我意识到在编译时不可能保证用户不会my_func<T>
错误地调用。但是我可以让它变得不太可能,并让它在早期产生运行时错误,如果他们这样做的话。
他们应该定义一个函数,比如说,initialise_library
. 该函数如下所示:
void initialise_library() {
my_func<int>();
my_func<char>();
etc..
}
在库初始化期间,它会检查以确保没有my_func
调用任何 s。然后它调用initialise_library
. 然后它会检查以确保所有的my_funcs
都已被调用。这是可行的。如果用户没有定义initialise_library
他们会得到一个链接器错误。如果他们没有my_func<T>
在他们的程序中调用my_class<T>
他们使用的某个地方,那么(理想情况下)他们会得到一个编译错误。如果他们已经定义initialise_library
并且他们已经在my_func<T>
某个地方使用过,但是他们在错误的地方使用了它,那么当他们的程序启动时就会出现运行时错误。
基本上我想阻止他们my_class<T>
在代码中的某个地方添加 a 并忘记my_func<T>()
输入initialise_library
,因为这是他们可能会做的事情。运行时检查的唯一方法是在构建my_class<T>
. my_class<T>
如果他们只在深度且很少使用的代码块中使用,这将是一个令人讨厌的后期检查。