在C+中多次调用给定函数时,是否有方法引发编译时错误+;? < C++ >有没有一种方法来设计一个函数/添加一些“属性”给它,这样调用代码中的几次会增加编译时错误?

在C+中多次调用给定函数时,是否有方法引发编译时错误+;? < C++ >有没有一种方法来设计一个函数/添加一些“属性”给它,这样调用代码中的几次会增加编译时错误?,c++,compile-time,error-checking,C++,Compile Time,Error Checking,给大家一点背景/动机:我在Mbed操作系统上编程,我犯了两个错误,看起来像: rtos::线程; [大量代码] 线程启动(持久化函数1); [设置函数中有大量代码] 线程启动(持久化函数2); 这产生了一个(逻辑)结果,即本应允许在程序生命周期内执行的持久化_函数_1,只有在线程被重新指定运行持久化_函数_2时才能执行。我花了很长时间才发现这个bug,我想知道我是否可以对我的线程做些什么。启动函数以确保在我再次犯这种错误时得到编译器错误。一个选项是将线程包装在一个新的管理器对象中,形状大致为

给大家一点背景/动机:我在Mbed操作系统上编程,我犯了两个错误,看起来像:

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