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
相关产品推荐
相关产品推荐

