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

C++20前如何让Lambda接收模板化大小的数组?求可行方案

C++17下实现带数组大小推导的实例校验方案

问题背景

我有一个用于创建Info类实例的宏,该类的构造函数接收带模板化大小的数组作为参数,大小信息用于校验。我希望在宏返回实例前执行校验(例如static_assert),原本计划让宏调用Lambda来执行校验并返回实例,但遇到了问题:将char数组传给Lambda的auto参数时会被推导为char指针,导致无法匹配Info的构造函数;而让Lambda接收带模板化大小的数组是C20才支持的特性。需要在C17中找到可行的替代方案。

可行替代方案

C++17不支持带模板参数的Lambda,因此我们可以用普通模板函数替代Lambda来封装校验逻辑,这样既能保留数组的大小信息,又能完成前置校验。

基础实现代码

#include <cstdlib>
#include <iostream>

class Info
{
public:
    template <size_t function_length, size_t file_length>
    Info(const char (&function)[function_length], const char (&file)[file_length])
        : function(function)
        , file(file)
    {
        // 构造函数内的字符串终止符校验
        if ('\0' != function[function_length - 1])
        {
            this->function = "invalid";
        }

        if ('\0' != file[file_length - 1])
        {
            this->file = "invalid";
        }
    }

    const char* function;
    const char* file;
};

// 封装校验逻辑的模板辅助函数
template <size_t func_len, size_t file_len>
Info create_info_impl(const char (&function)[func_len], const char (&file)[file_len])
{
    static constexpr char error_string[] = "invalid";

    // 自定义前置校验逻辑
    if ('m' != function[0])
    {
        return Info(error_string, error_string);
    }
    return Info(function, file);
}

// 简化调用的宏
#define CREATE_INFO() create_info_impl(__FUNCTION__, __FILE__)

int main()
{
    Info info = CREATE_INFO();

    std::cout << "Function: " << info.function << ", file: " << info.file << std::endl;

    return 0;
}

扩展:编译期强制校验(static_assert)

如果需要在编译期就强制校验规则,可以将校验逻辑封装为constexpr函数,配合static_assert使用:

template <size_t N>
constexpr bool is_valid_function_prefix(const char (&func)[N])
{
    return func[0] == 'm';
}

template <size_t func_len, size_t file_len>
Info create_info_impl(const char (&function)[func_len], const char (&file)[file_len])
{
    // 编译期断言:函数名必须以'm'开头
    static_assert(is_valid_function_prefix(function), "Function name must start with 'm'");
    
    static constexpr char error_string[] = "invalid";

    // 运行期字符串终止符校验
    if ('\0' != function[func_len - 1])
    {
        return Info(error_string, file);
    }
    if ('\0' != file[file_len - 1])
    {
        return Info(function, error_string);
    }
    return Info(function, file);
}

关键说明

C17标准中Lambda不支持模板参数声明(即[]<size_t N>(...)这种C20特性),因此无法直接让Lambda接收带模板化大小的数组。使用模板辅助函数是最直接且符合C++17规范的替代方案,既能完整保留数组的大小信息用于构造函数匹配,又能灵活实现前置校验逻辑。

内容的提问来源于stack exchange,提问作者Benjamin Bihler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:41:17