模板模板参数类型推导规则解析:filter函数为何无法自动推导?
模板模板参数的类型推导问题
我定义了三个使用模板模板参数的函数:
template <template <typename...> class ContainerType, typename ItemType> bool has_item(ContainerType<ItemType> items, ItemType target_item) { // ... } template <template <typename...> class ContainerType, typename ItemType> ContainerType<ItemType> filter(ContainerType<ItemType> items, const std::function<bool(ItemType)>& f) { // ... } template <template <typename...> class ContainerType, typename ItemType> bool is_vector(ContainerType<ItemType> items) { // ... }
原本认为编译器可以成功推导参数类型,但第二个函数似乎无法自动推导:
std::vector<int> v = {1, 2, 3, 4, 5}; std::cout << has_item(v, 1) << std::endl; // 正常 auto less_four = [](int x) { return x < 4; }; std::vector<int> v2 = filter<std::vector, int>(v, less_four); // 编译器无法自动推导 std::cout << is_vector(v2) << std::endl; // 正常
请问这三个函数之间存在什么差异,导致编译器无法为第二个函数自动推导类型?
原因分析
三个函数的核心差异在于参数类型与模板参数的绑定逻辑,推导失败的具体原因如下:
has_item与is_vector的推导逻辑has_item的两个参数直接对应模板参数:第一个参数ContainerType<ItemType>传入std::vector<int>时,编译器可直接推导出ContainerType=std::vector、ItemType=int;第二个参数ItemType传入int,进一步验证了推导结果,无冲突。is_vector仅接收ContainerType<ItemType>类型的参数,从传入的std::vector<int>即可直接推导出两个模板参数,逻辑简单直接。
filter的推导障碍filter的第二个参数是const std::function<bool(ItemType)>&,但传入的lambda是编译器生成的匿名闭包类型,与std::function属于不同类型。- C++模板类型推导的规则明确:仅进行直接类型匹配,不会自动执行隐式类型转换(包括lambda到
std::function这类用户定义转换)。 - 此时
ItemType需要从两个参数推导:第一个参数可推导出ItemType=int,但第二个参数的std::function<bool(ItemType)>无法与lambda类型匹配,推导链断裂,必须显式指定模板参数才能编译通过。
内容的提问来源于stack exchange,提问作者Chun-Ye Lu
相关产品推荐
相关产品推荐

