已知参数的模板扣除失败 [英] Template deduction fails for known argument

查看:151
本文介绍了已知参数的模板扣除失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码

  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 &)> from lambda

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆