我正在开发一个大型代码库,将一些旧的C模块转换为C ++。我想在结构中添加一个C ++对象,但是这个结构的一些用户memset
,这对于我想放在结构中的对象是不幸的。
如何在编译时检测到这是否已完成,以便我可以在不再是POD的结构上消除memset
的所有使用?
答案 0 :(得分:8)
我不确定编译器是否会通过直接提供一些编译标志来帮助你。如果确实如此,对你有好处。用那个。故事结束。
如果没有,那么这可能对你有帮助。由于您将代码从C转换为C ++,这意味着memset的所有用法都没有std::
命名空间。因此,请利用这一事实,#define memset
为:
#define memset memset_if_pod_else_error()
这里memset_if_pod_else_error
是您编写的函数(即您必须实现它)。您可以将其设为模板,以便推断出参数的类型,然后检测该类型是否为POD。如果是POD,则可以在内部调用std::memset
,否则会引发错误。
std::enable_if
和std::is_pod
等元功能将帮助您实现此功能。
以下是这个想法的最小演示:
#include <iostream>
#include <type_traits>
#include <cstring>
auto ptr_memset = std::memset; //store this a pointer
template<typename T>
using VoidPtr = typename std::enable_if<std::is_pod<T>::value, void*>::type;
#define memset memset_if_pod_else_error
template<typename T>
VoidPtr<T> memset_if_pod_else_error(T *data, int ch, size_t count)
{
return ptr_memset(data, ch, count);
}
struct pod {};
struct nonpod { nonpod() {} };
int main()
{
pod p;
nonpod np;
memset(&p, 0, sizeof(p));
memset(&np, 0, sizeof(np)); //this is error!
}
第二次调用memset
会产生此错误:
错误:没有匹配函数来调用'memset_if_pod_else_error'
memset(&amp; np,0,sizeof(np));
^ ~~~~~
希望有所帮助。
答案 1 :(得分:2)
这个怎么样:
auto orig_memset = std::memset;
#define memset checked_memset
template <class T>
void* checked_memset(T* ptr, int value, size_t num) {
static_assert(std::is_pod<T>::value, "memset on non-POD");
return original_memset(data, value, num);
}
或者,如果您只对查找特定结构的违规行为感兴趣:
auto original_memset = std::memset;
#define memset checked_memset
template <class T>
void* checked_memset(T* ptr, int value, size_t num) {
static_assert(!std::is_same<T, YOUR_STRUCT_HERE>::value, "memset used on YOUR_STRUCT_HERE");
return original_memset(data, value, num);
}
答案 2 :(得分:1)
我认为您无法在编译时检测到对非POD数据使用memset
。
您可以做的是添加一些在构造函数中设置的额外字段,然后在任何其他成员函数中进行检查。像这样:
class X
{
const int MAGIC = 123456789;
int magic;
...
public:
X() : magic(MAGIC) { ... }
...
void do_stuff()
{
check_magic();
...
}
private:
void check_magic()
{
if (magic != MAGIC) { ... do something to indicate bad state ... };
}
};
显然,这可以“仅在调试版本上”完成。
答案 3 :(得分:0)
在这种情况下,不是试图找到所有问题区域,我建议首先防止它们。具体来说,不要将任何C ++功能添加到现有的C结构中,而是使用包含C数据结构实例的适当的interfcace编写类。然后,您将保持与旧结构和代码的完全向后兼容性,以及添加您感兴趣的新C ++功能。