我可以静态地阻止一个函数调用另一个函数吗
Can I statically prevent one function from calling another?
我有以下接口:
class T {
public:
// Called in parallel
virtual unsigned validate () = 0;
// Called with a lock taken out
virtual unsigned update () = 0;
};
template <typename DataType>
class Cache {
public:
// Gets the requested object.
// If it doesn't exist in memory, go to SQL.
unsigned fetch (DataType &data);
// Gets the requested object.
// If it's not in memory, returns NOT_FOUND.
unsigned find (DataType &data);
};
我想要实现的目标:如果在update
期间调用fetch
,我希望能够使编译失败。实际上,我想根据调用站点静态禁用该函数。类似
std::enable_if <callsite_is_not_implementation_of_T_update, unsigned>
fetch (DataType &data);
用法如下:
class A_T : public T {
public:
virtual unsigned validate () {
global_cache.fetch (object); // OK
}
virtual unsigned update () {
global_cache.find (object); // Also OK
global_cache.fetch (object); // FAIL!
}
};
背景
在我的项目中大约有500个T
的实现。
应用程序在许多线程中循环,并并行地为T
的许多实例调用validate
。然后取出一个全局锁,并调用update
。因此,update
的速度至关重要。一般的态度是在validate
期间花你需要的任何时间,但update
应该尽可能瘦。
我的问题是使用Cache
。Cache
基本上是SQL中数据对象的内存缓存。
策略是在update
期间永远不要调用Cache::fetch
,因为持有锁时可能会发生SQL往返。我们都在努力在团队中培养这种心态。不幸的是,其中一些仍然偷偷出现,并通过了代码审查。只有当系统负载过重,一切都陷入停顿时,我们才会注意到它们。
我想建立一个安全网,防止这种事情被允许。如果从T::update
调用Cache::fetch
,我想实现的是编译失败。
我不介意是否可以解决。关键是要把它作为一道屏障;你可能犯错误的唯一方法就是故意去做。
到目前为止我得到了什么
我已经走了一段路,虽然不是我真正想要的。例如,我不希望每次调用都更改为fetch
。
template <typename Impl>
class cache_key {
cache_key() { }
friend unsigned Impl::validate();
};
#define CACHE_KEY cache_key<std::remove_pointer<decltype(this)>::type> ()
所以现在Cache::fetch
看起来像:
unsigned fetch (DataType &object, const cache_key &key);
T
的实现可能如下所示:
class A_T : public T {
public:
virtual unsigned validate () {
global_cache.fetch (object, CACHE_KEY); // OK
}
virtual unsigned update () {
global_cache.fetch (object, CACHE_KEY); // Can't do it!
}
};
我不知道编译时错误的生成,但可以通过只更新基类来生成运行时错误。
一种方法是通过基类中的非虚拟代理函数调用update,该函数会将状态设置为基类,以检测我们正在更新,因此不应调用fetch。
class updateWatcher()
{
public:
updateWatcher(bool *valIn) : val(valIn) {*val=true;}
~updateWatcher() {*val=false;}
private:
bool* val;
}
class T {
public:
// Called in parallel
virtual unsigned validate () = 0;
unsigned updateProxy()
{
updateWatcher(&inUpdate); //exception safe tracker we are in update
return update();
}
void
protected:
// Called with a lock taken out
virtual unsigned update () = 0;
bool inUpdate; // tells if we are in update or not
};
class A_T : public T {
public:
virtual unsigned validate () {
global_cache.fetch (object,inUpdate); // OK
}
virtual unsigned update () {
global_cache.find (object); // Also OK
global_cache.fetch (object,inUpdate); // FAIL (put assert in global_cache.fetch) !
}
};
这不会产生编译而是运行时错误,好处是不需要更新任何实现(除了替换所有global_cache.fetch(…);通过global_cache.fetch(…,inUpdate);并调用update()到updateProxy();在所有实现中都可以有效地自动化)。然后,您可以将一些自动化测试集成为构建环境的一部分,以捕获断言。
这只是一个愚蠢的POC,我不推荐它,可能无法满足您的期望:
struct T {
// Called in parallel
virtual unsigned validate () = 0;
// Called with a lock taken out
virtual unsigned update () = 0;
};
struct A_T : T {
unsigned validate () override;
unsigned update () override;
};
template <typename DataType>
class Cache {
private:
class Privileged {
friend class Cache<DataType>;
friend unsigned A_T::validate();
Privileged( Cache<DataType> &outer ) : outer(outer) {}
// Gets the requested object.
// If it doesn't exist in memory, go to SQL.
unsigned fetch (DataType &data);
Cache<DataType> &outer;
};
public:
Privileged privileged { *this };
// Gets the requested object.
// If it's not in memory, returns NOT_FOUND.
unsigned find (DataType &data);
};
Cache<int> global_cache;
unsigned A_T::validate () {
int object;
global_cache.privileged.fetch (object); // OK
return 1;
}
unsigned A_T::update () {
int object;
global_cache.find (object); // Also OK
global_cache.privileged.fetch (object); // FAIL!
return 1;
}
- 使用另一个函数调用一个函数(都在类中)时出现问题.没有错误代码C++
- 重载运算符主体仅包含一个函数调用
- 在 MySQL 连接器C++ API 中使用一个函数调用执行多个查询的正确方法是什么?
- C++编译器在一个源文件中的一个函数调用中引发错误,但在具有相同函数调用的另一个源文件中不会引发错误
- while 循环在一个函数调用中执行两次
- 在C++中嵌入Python:在Python脚本中导入模块在一个函数调用过程中有效,但在另一个调用过程中无效
- 如何从前面定义的另一个函数调用函数模板
- 下面的代码会被优化为一个函数调用吗
- C++中的神秘:函数调用行为不端只是因为存在另一个函数调用,即使它们是不相关的
- 我可以静态地阻止一个函数调用另一个函数吗
- c++oop初学者-在一个函数调用中返回向量中每个创建对象的输出和
- 如何告诉编译器向编译的每个函数添加一个函数调用
- 存储一个函数的迭代结果,并在被另一个函数调用时使用它们
- 在一个函数调用中创建线程池,并从另一个函数调用来使用它
- 如何使用谷歌测试零或一个函数调用进行检查
- 一个函数调用另一个函数时使用的内存会发生什么情况
- 从一个函数调用另一个函数
- 只需一个函数调用即可输出分数
- 在C/ c++中,当两个函数具有相同的名称,一个函数调用另一个函数时,它将工作
- 为什么arduino忽略了一个函数调用