在C+中多次调用给定函数时,是否有方法引发编译时错误+;? < C++ >有没有一种方法来设计一个函数/添加一些“属性”给它,这样调用代码中的几次会增加编译时错误?
给大家一点背景/动机:我在Mbed操作系统上编程,我犯了两个错误,看起来像:在C+中多次调用给定函数时,是否有方法引发编译时错误+;? < C++ >有没有一种方法来设计一个函数/添加一些“属性”给它,这样调用代码中的几次会增加编译时错误?,c++,compile-time,error-checking,C++,Compile Time,Error Checking,给大家一点背景/动机:我在Mbed操作系统上编程,我犯了两个错误,看起来像: rtos::线程; [大量代码] 线程启动(持久化函数1); [设置函数中有大量代码] 线程启动(持久化函数2); 这产生了一个(逻辑)结果,即本应允许在程序生命周期内执行的持久化_函数_1,只有在线程被重新指定运行持久化_函数_2时才能执行。我花了很长时间才发现这个bug,我想知道我是否可以对我的线程做些什么。启动函数以确保在我再次犯这种错误时得到编译器错误。一个选项是将线程包装在一个新的管理器对象中,形状大致为
rtos::线程;
[大量代码]
线程启动(持久化函数1);
[设置函数中有大量代码]
线程启动(持久化函数2);
这产生了一个(逻辑)结果,即本应允许在程序生命周期内执行的
持久化_函数_1
,只有在线程被重新指定运行持久化_函数_2
时才能执行。我花了很长时间才发现这个bug,我想知道我是否可以对我的线程做些什么。启动函数以确保在我再次犯这种错误时得到编译器错误。一个选项是将线程包装在一个新的管理器对象中,形状大致为
类线程管理器{
rtos::线程;
const std::函数执行函数;
/* .
.
. */
公众:
线程管理器(rtos::线程_线程,std::函数,…)
:thread{u thread}
,执行函数{function}
, ...
void start();
}
不允许任何其他线程的使用(可以基于封装来证明,虽然在注释中指出,YaHOOS总是有风险)。
< P>我不认为在编译时有直接强制C++语言检测<代码>启动()/代码>的双重调用的方法。(换言之,我认为@user4581301的建议行不通):要静态断言属性,您需要以某种方式更改实体。我相信您可以使用编写自定义检查器,但我猜这不是您想要的。显然,有可能有一个运行时断言来报告已start()
ed线程再次启动。同样,这似乎不是您想要的
“显而易见”的解决方案是在一个函数中没有“[大量代码]
”作为开始。事实上,std::thread
完全是通过强制在对象声明和它的开始之间没有代码来解决问题的。std::thread
是在构造时启动的。带有“[大量代码]
的设置。”在对象声明和开始之间
my::thread thread([&]{
[lots of code]
return persistent_function_1;
}());
my::thread thread([](my::thread::properties& properties) {
[lots of code manipulating the properties]
},
persistent_function_1);
需要注意的是,您需要按顺序设置各种变量。也就是说,首选方法是在实际启动的站点声明线程对象:
[lots of code]
my::thread thread(persistent_function_1);
在这两种情况下,my::thread
将是rtos::thread
的一个微不足道的包装器,它不会公开一个单独的start()
方法
一个合理的原因可能是能够设置各种线程参数,实际使用两个单独的参数来设置my::thread
的构造函数可能是合理的:
以my::thread::properties
实体作为参数的函数,允许对thread
对象进行必要的操作
要启动的函数
就是说,
my::thread thread([&]{
[lots of code]
return persistent_function_1;
}());
my::thread thread([](my::thread::properties& properties) {
[lots of code manipulating the properties]
},
persistent_function_1);
通过这种方式,仍然可以操作线程
,但不能将开始()
线程操作两次。当前没有检测两次出现的表达式的机制。但是,您可以通过折磨编译器来接近它
名称空间
{
模板
构造一次
{
一次(){}
友元无效重定义(){}
};
}
#定义一次(expr)(一次{},(expr))
如果一次
在同一TU中出现两次,编译器将抱怨重新定义重定义
一次(thread.start(persistent_function_1));//确定
一次(thread.start(persistent_function_2));//错误
必须有一种方法来包装线程。在设置布尔值或计数器的模板中启动
,并在静态断言中测试布尔值。当然,然后一些yahoo会调用线程。如果没有模板,启动
,你也不会更好。是的,这已经是一个很好的改进。我同意这仍然可能会失败是的,但是在代码库上可能有一个“不应该使用裸线程声明”的策略.老实说,我不是100%确定它能做到,但每次我认为有些事情不能做到时,似乎有个聪明的家伙放弃了一个模板元程序来做。通常模板是如此疯狂,它比它试图治愈的东西更糟糕,但我想说的真正点是,无论你做什么,都可以阻止你调用start
,someone将直接调用start
。唯一明智的做法是使预防变得不必要,或者在代码审查过程中使错误变得明显。@user4581301:我同意经常有人出现,并找到一种方法来做一些以前认为不可能的事情(很久以前我自己也这样做过,当时我发现一个函数模板推断内置数组的大小,即现在内置数组的std::end()
)但是,我认为没有办法改变名字的静态属性,我也不知道即使涉及宏也可以使用不同的名称。因此,我提出的解决问题的方法是使用一个不同的接口。要正确地处理这个问题,我需要了解更多关于<代码> RTOS::线程< /C> >,但是C++。(和大多数编程语言一样)旨在帮助程序员避免意外错误。无法阻止“yahoo”(也就是那些故意绕过某个约束的人)把事情弄糟。如果代码可以编写成preven