针对 std::function 的 lambda 表达式和模板推导:为什么这有效?
lambda expression and template deduction against std::function: why this works?
我的问题与这个问题有些相关:
Lambdas and std::function。请阅读此问题及其接受的答案。
所以,接受的答案说以下代码使针对 lambda 的模板参数推导成功,但为什么呢?
template<class T>
struct Identity{
typedef T type;//why this helps?
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });//lambda here.
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
上面的代码可以运行,但我不知道为什么。首先,我知道 lambda 不会发生 BaseT
的模板推导,因为这是一个不可推导的上下文 (Identify<function<bool (const BaseT &)>>::type
)。相反,BaseT
从 testv
推导为 int
,并且模板参数替换发生在 Identity<function<bool (const BaseT &)>>::type
中。
但下一步是什么?替换后,Identity<function<bool (const BaseT &)>>::type
变成了function<bool (const BaseT &)>
,但是lambda表达式不就是这种类型吗,模板参数推导中不会发生转换(虽然这里是模板参数替换)?
感谢您的解释!
P.S。我似乎知道编译器为每个 lambda 表达式生成唯一命名的 class 。那么为什么lambda可以匹配到function<bool (const BaseT &)>
呢?
这是有效的,因为 func
参数的类型是 而不是 推导的。
通过使用外部特征 class Idendity
,代码使 func
参数的类型依赖于 BaseT
模板参数,将其转换为非推导上下文。
因此,发生的事情是 BaseT
被推导出为 search
参数并且事实上 func
的类型依赖于 BaseT
,变得已知.最后,您的 lambda 可以隐式转换为所需的 std::function<bool(int const&)>
类型。
如果省略此技巧使 func
的类型依赖于 BaseT
,例如:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
function<bool (const BaseT &)> func)
然后,func
也会发生模板参数推导,并会产生编译器错误。
But what's next? after substitution, Identity<function<bool (const BaseT &)>>::type
becomes function<bool (const BaseT &)>
, but isn't lambda expression not of that type, and conversions does not happen in template parameter deduction(although here is template parameter substitution)?
你是对的,在模板参数推导过程中没有替换,但是一旦完成,我们就将函数调用视为调用实例化函数。
这意味着 Identity<function<bool (const BaseT &)>>::type
已替换为 function<bool (const BaseT &)>
您正在调用的实例化函数是:
vector<int> findMatches(vector<int> search, function<bool (const int&)> func)
因为它采用的是具体的 function<bool (const int&)>
lambda 可以用来构造 func
我的问题与这个问题有些相关: Lambdas and std::function。请阅读此问题及其接受的答案。
所以,接受的答案说以下代码使针对 lambda 的模板参数推导成功,但为什么呢?
template<class T>
struct Identity{
typedef T type;//why this helps?
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });//lambda here.
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
上面的代码可以运行,但我不知道为什么。首先,我知道 lambda 不会发生 BaseT
的模板推导,因为这是一个不可推导的上下文 (Identify<function<bool (const BaseT &)>>::type
)。相反,BaseT
从 testv
推导为 int
,并且模板参数替换发生在 Identity<function<bool (const BaseT &)>>::type
中。
但下一步是什么?替换后,Identity<function<bool (const BaseT &)>>::type
变成了function<bool (const BaseT &)>
,但是lambda表达式不就是这种类型吗,模板参数推导中不会发生转换(虽然这里是模板参数替换)?
感谢您的解释!
P.S。我似乎知道编译器为每个 lambda 表达式生成唯一命名的 class 。那么为什么lambda可以匹配到function<bool (const BaseT &)>
呢?
这是有效的,因为 func
参数的类型是 而不是 推导的。
通过使用外部特征 class Idendity
,代码使 func
参数的类型依赖于 BaseT
模板参数,将其转换为非推导上下文。
因此,发生的事情是 BaseT
被推导出为 search
参数并且事实上 func
的类型依赖于 BaseT
,变得已知.最后,您的 lambda 可以隐式转换为所需的 std::function<bool(int const&)>
类型。
如果省略此技巧使 func
的类型依赖于 BaseT
,例如:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
function<bool (const BaseT &)> func)
然后,func
也会发生模板参数推导,并会产生编译器错误。
But what's next? after substitution,
Identity<function<bool (const BaseT &)>>::type
becomesfunction<bool (const BaseT &)>
, but isn't lambda expression not of that type, and conversions does not happen in template parameter deduction(although here is template parameter substitution)?
你是对的,在模板参数推导过程中没有替换,但是一旦完成,我们就将函数调用视为调用实例化函数。
这意味着 Identity<function<bool (const BaseT &)>>::type
已替换为 function<bool (const BaseT &)>
您正在调用的实例化函数是:
vector<int> findMatches(vector<int> search, function<bool (const int&)> func)
因为它采用的是具体的 function<bool (const int&)>
lambda 可以用来构造 func