You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++实现间隔N次调用执行函数的静态变量冲突及返回值约束问题

问题解决方法

1. 核心问题分析

计数器共用问题

原有实现中计数器共用的根因是:C++模板函数的静态变量属于每个独立的模板实例,当多个调用的模板参数(N、Callable类型、Args类型)完全相同时,编译器只会生成一份函数实例,对应的静态计数器自然会被多个调用位点共享。
示例中两处CALL_EVERY_N(3, test, i, 1)和CALL_EVERY_N(3, test, i, 2)的模板参数完全一致,因此共用计数器。

返回值约束问题

需要利用C++类型萃取工具校验可调用对象传入指定参数后的返回值是否为void。


2. 解决方案代码(兼容C++17及以上)

修改后的实现

#include <cstddef>
#include <functional>
#include <utility>
#include <type_traits>

// 新增Line模板参数,用于区分不同调用位点
template<size_t N, size_t Line, typename Callable, typename... Args>
void call_every_n(Callable&& c, Args&&... args)
{
    static size_t call_count = 0;
    // 约束返回值必须为void
    static_assert(std::is_invocable_r_v<void, Callable, Args...>, 
                  "The input callable must return void when invoked with given arguments");
    
    if(call_count == N - 1)
    {
        std::invoke(std::forward<Callable>(c), std::forward<Args>(args)...);
        call_count = 0;
    } else {
        ++call_count;
    }
}

// 宏中传入__LINE__作为Line模板参数,保证不同行的调用实例独立
#define CALL_EVERY_N(N, FUNC, ...) call_every_n<N, __LINE__, decltype(FUNC), decltype(__VA_ARGS__)>(FUNC, __VA_ARGS__)

测试运行结果

运行示例中的main函数测试用例,输出符合预期:

1 = 3
2 = 3
1 = 6
2 = 6
1 = 9
2 = 9
1 = 12
2 = 12
1 = 15
2 = 15
1 = 18
2 = 18

两个调用位点各自独立计数,每调用3次触发一次目标函数。


3. C++20优化版本(可选)

如果使用C++20及以上标准,可以用std::source_location替代__LINE__,支持更精准的位点区分(覆盖同一行多次调用、不同文件同行数调用的场景),同时可以用concept简化类型约束:

#include <source_location>

template<size_t N, typename Callable, typename... Args>
requires std::is_invocable_r_v<void, Callable, Args...>
void call_every_n(Callable&& c, Args&&... args, const std::source_location& loc = std::source_location::current())
{
    struct CounterHolder { size_t count = 0; };
    static thread_local CounterHolder counter;
    if(counter.count == N -1) {
        std::invoke(std::forward<Callable>(c), std::forward<Args>(args)...);
        counter.count = 0;
    } else {
        counter.count++;
    }
}
// 此时宏不需要额外传参
#define CALL_EVERY_N(N, FUNC, ...) call_every_n<N>(FUNC, __VA_ARGS__)

内容的提问来源于stack exchange,提问作者Jacopo Lottero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:27:03