简体   繁体   English

为什么Type Traits在命名空间(std :: enable_if)内部不起作用-C ++ 11

[英]Why Type Traits is not working inside namespace (std::enable_if) - c++11

If the following code is placed inside a namespace then its not working, but without namespace its working fine... 如果将以下代码放置在命名空间中,则它将无法正常工作,但是如果没有命名空间,它将无法正常工作...

template <typename T,typename _F>
inline typename std::enable_if< is_iterable<T>::value >::type
for_all_ele(T&& arr,_F&& fn)
{
    for(auto &x:arr)
        for_all_ele(x,fn);

}

template <typename T,typename _F>
inline typename std::enable_if< not is_iterable<T>::value >::type
for_all_ele(T&& x,_F&& fn)
{
    fn(x);
}

is_iterable is defined over it... is_iterable是在上面定义的...

The full code is here : http://ideone.com/goJ0Zf 完整的代码在这里: http : //ideone.com/goJ0Zf

Till now all I can find is the template specialization of 'for_all_ele' for scalar data is not being detected inside namespace... 直到现在我能找到的是'for_all_ele'的模板特化,因为在名称空间中没有检测到标量数据...

Your recursion works when it is found via Koenig Lookup (aka ADL, aka Argument Dependent Lookup) and not when it is not found that way. 通过Koenig查找(又名ADL,又称自变量依赖查找)找到您的递归,而不是通过这种方式找不到它。

This call: 这个电话:

{
  for(auto &x:arr)
    for_all_ele(x,fn);
}

does not see the later declared for_all_ele , unless one of x or fn finds it via ADL. 不会看到后来声明的for_all_ele除非 xfn之一通过ADL找到了它。 As it happens, when it isn't in a namespace, the lambda you pass as fn is in the same (root) namespace as your for_all_ele function is. 碰巧的是,当它不在名称空间中时,以fn身份传递的lambda与for_all_ele函数位于相同的(根)名称空间中。 So it is found. 这样就找到了。

When for_all_ele is in a namespace, it doesn't work, because the lambda is in a different namespace. for_all_ele在名称空间中时,它不起作用,因为lambda在其他名称空间中。

There are three approaches. 有三种方法。

First, you can forward-declare it. 首先,您可以向前声明它。

Second, you can create a wrapping function. 其次,您可以创建包装功能。 It then instantiates a toy type ( struct toy_tag{}; ) and passes it together with the other arguments to the for_all_ele_impl , which pass said toy_tag when they recurse. 然后,它实例化玩具类型( struct toy_tag{}; )并将其与其他参数一起传递给for_all_ele_impl ,后者在递归时将其传递给所述toy_tag

Third, you can simply move the recursive case after the terminating case: https://ideone.com/17h75Q 第三,您可以简单地将递归条件移到终止条件之后: https : //ideone.com/17h75Q

template <class T, class F>
inline typename std::enable_if< is_iterable<T>::value >::type
for_all_ele(T&& arr,F&& f)
{
  for(auto&&x:arr)
    for_all_ele(decltype(x)(x),f);
}

template <class T, class F>
inline typename std::enable_if<
  !is_iterable<T>::value
>::type
for_all_ele(T&& t,F&& f) {
  std::forward<F>(f)(std::forward<T>(t));
}

I renamed your _F to F , as the name _F is reserved by the standard in all contexts. 我将您的_F重命名为F ,因为标准在所有情况下都保留名称_F I also perfect forwarded the function object, because I'm like that. 我也很完美地转发了函数对象,因为那样。 And I did some perfect forwarding your code was missing. 我做了一些完美的转发,您的代码丢失了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM