优化将捕获Lambda作为构造参数的indexed_vec实例化语法
解决indexed_vec实例化繁琐的最优方案:工厂函数
你的问题核心在于,indexed_vec作为模板类,需要手动指定ValueType和两个Lambda的闭包类型——而每个Lambda都是编译器生成的匿名类型,手动写decltype会让代码非常冗长,推导指南也因为闭包类型的特殊性没法生效。用工厂函数模板是最直接的解决办法,让编译器自动帮你推导所有模板参数。
具体实现
- 保留原有
indexed_vec结构:不用修改核心逻辑,确保构造函数能接收两个订阅者Lambda即可:
template <typename ValueType, typename Subscriber1, typename Subscriber2> struct indexed_vec { std::vector<ValueType> data; // 按你说明设为公共成员 Subscriber1 sub1; Subscriber2 sub2; // 基础构造:仅接收订阅者 indexed_vec(Subscriber1 s1, Subscriber2 s2) : sub1(std::move(s1)), sub2(std::move(s2)) {} // 带初始元素的构造 indexed_vec(std::initializer_list<ValueType> init, Subscriber1 s1, Subscriber2 s2) : data(init), sub1(std::move(s1)), sub2(std::move(s2)) {} };
- 实现工厂函数:利用函数模板的自动推导特性,省去手动指定模板参数的麻烦:
// 带初始元素:自动推导ValueType和订阅者类型 template <typename ValueType, typename Subscriber1, typename Subscriber2> auto make_indexed_vec(std::initializer_list<ValueType> init, Subscriber1 sub1, Subscriber2 sub2) { return indexed_vec<ValueType, Subscriber1, Subscriber2>(init, std::move(sub1), std::move(sub2)); } // 空实例化:显式指定ValueType,自动推导订阅者类型 template <typename ValueType, typename Subscriber1, typename Subscriber2> auto make_indexed_vec(Subscriber1 sub1, Subscriber2 sub2) { return indexed_vec<ValueType, Subscriber1, Subscriber2>(std::move(sub1), std::move(sub2)); }
- 使用对比:
原来的繁琐写法:
auto sub1 = [](size_t old_idx, size_t new_idx) { /* 索引更新逻辑 */ }; auto sub2 = [](size_t old_idx) { /* 删除清理逻辑 */ }; // 必须手动指定所有模板参数,闭包类型还要用decltype indexed_vec<int, decltype(sub1), decltype(sub2)> vec(sub1, sub2);
用工厂函数后的简洁写法:
auto sub1 = [](size_t old_idx, size_t new_idx) { /* 索引更新逻辑 */ }; auto sub2 = [](size_t old_idx) { /* 删除清理逻辑 */ }; // 空容器:只需要显式指定存储的ValueType,订阅者自动推导 auto vec = make_indexed_vec<int>(sub1, sub2); // 带初始元素:ValueType会自动从初始化列表推导 auto vec_with_data = make_indexed_vec({1, 2, 3}, sub1, sub2);
额外说明
- 推导指南为啥没用?因为Lambda的闭包类型是匿名的,没法在推导指南里提前定义匹配规则,而函数模板的参数推导可以直接捕获这些匿名类型,完美适配你的场景。
- 如果需要支持更多构造方式(比如从迭代器范围初始化),只需要重载对应的工厂函数就行,保持接口一致性。
- 用
std::move转移Lambda所有权是好习惯,虽然Lambda通常体积很小,但能避免不必要的拷贝。
内容的提问来源于stack exchange,提问作者Oliver Schönrock
相关产品推荐
相关产品推荐

