C++编译时检查函数是否被使用/未被使用

6
我希望在编译期间检查某个类的某个函数是否被使用,然后根据情况通过/未通过编译。
例如,如果代码中有调用F1函数的地方,我希望编译成功;如果调用F2函数则希望编译失败。
有没有什么想法可以使用预处理器、模板或其他c++元编程技术来实现?

1
“如果要求调用F1函数必须成功”是一个奇怪的要求。您的意思是:“如果没有调用F1函数,它将无法编译”吗? - Daniel Frey
另一个问题是:“在编译时……” - 但该函数可能在不同的翻译单元中使用! - Daniel Frey
4
更改函数名称,连接器会告诉你是否被使用。 - mah
1
编译器无法判断是否调用了外部函数,只能判断当前正在编译的翻译单元中定义的函数。我没有找到任何适合的命令行选项(-Wunused-function 只会警告非内联 static 函数)。在链接器标志中也没有找到合适的内容。你可能需要让链接器创建一个映射文件,如果它包含该信息,则解析该文件并发出构建过程错误。 - Some programmer dude
3
你能告诉我们更多关于为什么你想要那个吗?我很确定有一个更好的解决方案来解决实际问题。 - us2012
显示剩余3条评论
2个回答

6

如果您愿意修改F2函数的函数体并在其中添加一个静态断言(static_assert),并将一个虚假的模板添加到函数签名中,则可以使用C++11编译器来实现此目标:

#include <type_traits>

void F1(int) {    
}

template <typename T = float>
void F2(int) {
    static_assert(std::is_integral<T>::value, "Don't call F2!");
}

int main() {
 F1(1);  
 F2(2);  // Remove this call to compile
}

如果 F2 没有调用者,代码将会编译。具体原因请参见此答案,了解为什么我们需要使用模板技巧,而不能简单地插入 static_assert(false, "");

...并删除F2的旧实现。 - Angew is no longer proud of SO
不需要删除旧的实现,只需修改现有的实现即可。 - user425495
1
将其移至头文件。如果不这样做,您将在调用站点处收到未定义模板的错误(而不是触发static_assert)。我想这仍然足以实现“如果调用F2则出现编译时错误”的效果。 - Angew is no longer proud of SO
同意;我在我的示例中忘记考虑到这一点了。按照@mah的评论重命名函数可能会更方便地实现编译时错误。 - user425495
看起来是个不错的方向...那我们能不能让它变得更加复杂一些呢 :-)假设我有一组函数 F1...Fn 和一组类 C1...Cm,是否有一种方法可以使代码在已知规则集下编译/不编译,在每个类 Ci 中只允许调用函数 F1..Fn 的一个子集(对于每个类不同的子集)。而且,如果我想要保证完整性,情况会更加复杂。也就是说,确保某个函数从某个地方被调用。 - Max Shifrin
缺点是将F2(int)转换为模板会影响重载解析。突然之间,F2(something)可能会调用不同的F2 - 463035818_is_not_a_number

1

这不是一个非常模板化的解决方案,但您可以依赖编译器的“deprecated”属性,如果某个函数在任何地方被使用,它将生成警告。

在MSVC中,您可以使用__declspec(deprecated)属性:

__declspec(deprecated("Don't use this")) void foo();

G++:

void foo() __attribute__((deprecated));

如果您打开了“将警告视为错误”的编译选项(通常应该这样做),则会得到所需的行为。
int main() 
{
    foo(); // error C4966: 'foo': Don't use this
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接