已知参数的模板扣除失败 [英] Template deduction fails for known argument
问题描述
请考虑以下代码
template< typename T&
T modify(const T& item,std :: function< T(const T&)> fn)
{
return fn
}
当尝试使用 modify(5, [](const int& i){return 10 * i;});
无法编译
无法从
lambda
中推导出'std :: function< T(const T&
我知道编译器不能从lambda推导出 T
,因为lambda不是 std :: function
,但不是 T
已从 5推导出$
template< typename T,typename F>
T modify(const T& item,const F& functor)
{
return functor(item);
}
,但在我看来,是否有一种方法让函数参数保留 std :: function
并让它的模板参数自动从 item
?
你基本上要做的是防止扣款发生。如果发生模板扣除,它将失败(因为lambda不是 std :: function
T
是从第一个参数中推导出来的,扣除必须在每个参数都成功推导的上下文中成功)。防止扣除的方法是将整个参数粘贴在非推导的上下文中,最简单的方法是将类型转换为 nested-name-specifier 。我们创建这样的类型包装:
template< class T& struct non_deduce {using type = T; };
template< class T>使用non_deduce_t = typename non_deduce< T> :: type;
然后将类型包含在其中:
template< typename T>
void foo(const T& item,std :: function< void(T)> f);
template< typename T>
void bar(const T& item,non_deduce_t< std :: function< void(T)>>
foo(4,[](INT){}); // error
bar(4,[](int){}); //确定,我们从项目中推导T为int,
//这使得类型为std :: function< void(int)>
但请注意:
template< typename T,typename F>
void quux(const T& F);
实际上不是很少可读,
Consider following code
template<typename T>
T modify(const T& item, std::function<T(const T&)> fn)
{
return fn(item);
}
When trying to use it as modify(5, [](const int& i){return 10*i;});
it fails to compile with
could not deduce template argument for
'std::function<T(const T &)>
fromlambda
I know that compiler can not deduce T
from lambda, because lambda is not std::function
, but isn't T
already deduced from 5
?
I can get over it using
template<typename T, typename F>
T modify(const T& item, const F& functor)
{
return functor(item);
}
for which previous example compiles, but it is in my opinion less intuitive. Is there a way to let the function argument to remain std::function
and have it's template argument deduced automatically from item
?
What you basically want to do is prevent deduction from happening. If template deduction occurs, it will fail (because a lambda is not a std::function<>
- it doesn't matter that T
was deduced from the first argument, deduction must succeed in every argument that is a deduced context). The way to prevent deduction is to stick the entire argument in a non-deduced context, the easiest way of doing that is to throw the type into a nested-name-specifier. We create such a type wrapper:
template <class T> struct non_deduce { using type = T; };
template <class T> using non_deduce_t = typename non_deduce<T>::type;
And then wrap the type in it:
template<typename T>
void foo(const T& item, std::function<void(T)> f);
template<typename T>
void bar(const T& item, non_deduce_t<std::function<void(T)>> f);
foo(4, [](int ){} ); // error
bar(4, [](int ){} ); // ok, we deduce T from item as int,
// which makes f of type std::function<void(int)>
Note, however, that:
template <typename T, typename F>
void quux(const T&, F );
is not really any less readable, and strictly more performant.
这篇关于已知参数的模板扣除失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!