我有一个带有两个模板参数的模板函数。
第一个(T)是根据第一个参数的类型推导出来的。第二种方法(ItrT)是利用std::type_traits和T推导出来的。
当我使用ItrT作为参数的类型(参见函数bar)时,所有类型都是隐式推导的,但是当我使用std::function<void(ItrT)>作为参数的类型(参见函数foo)时,只有在完全指定所有模板参数时才能推断正确的类型(即使使用与函数定义完全相同的代码)。可以想象,在模板中使用ItrT不会改变编译器推断模板的能力。
为什么不是这种情况?我需要做些什么,以便隐式地推导出所有的模板参数?
我在用C++17。
template <class T, class ItrT = typename std::iterator_traits<T>::value_type>
auto foo(T iterator, std::function<void(ItrT)> expr) -> void{
}
template <class T, class ItrT = typename std::iterator_traits<T>::value_type>
auto bar(T iterator, ItrT expr) -> void{
}
int main() {
std::vector<int> vec = {1, 2, 3};
bar(vec.begin(), 1); // Compiles!
foo(vec.begin(), [](int) {}); // Failes!
foo<decltype(vec.begin()),
std::iterator_traits<decltype(vec.begin())>::value_type>
(vec.begin(), [](int) {}); // Compiles!
}发布于 2018-09-08 02:33:41
我猜这里的困惑是关于默认模板参数的角色。
规则不是:尝试推断一个参数。如果扣减失败,则使用默认值(如果提供)。
相反,规则是:如果参数在推导的上下文中,则推导它。如果扣减失败,中止。如果它不是在推导的上下文中,并且没有显式提供,那么使用默认的参数。换句话说,只有在参数既不是在推导的上下文中也没有显式提供的情况下,才会使用默认参数。
在这两个示例中,ItrT都位于推导的上下文中,因此根本不考虑默认的模板参数。两者的区别在于,您可以从lambda中推断出T (只匹配它的类型),但是不能从lambda中推断出function<void(T) -- lambda可以转换为适当的function,但是lambda不是function。模板演绎不进行转换。模板演绎只与模式匹配。
https://stackoverflow.com/questions/52230730
复制相似问题