用`std :: enable_if`和非推导上下文重载函数模板 [英] Overloaded function template disambiguation with `std::enable_if` and non-deduced context

查看:105
本文介绍了用`std :: enable_if`和非推导上下文重载函数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

template <typename T>
struct dependent_type
{
    using type = T;
};

template <typename T>
auto foo(T) -> std::enable_if_t<std::is_same<T, int>{}>
{
    std::cout << "a\n"; 
}

template<typename T> 
void foo(typename dependent_type<T>::type) 
{
    std::cout << "b\n";
}

  • foo的第一个重载可以从其调用中推断出T.

    • The first overload of foo can deduce T from its invocation.

      foo的第二个重载是 非推论上下文 .

      The second overload of foo is a non-deduced context.

      int main()
      {    
          foo<int>( 1 );      // prints "b"
          foo<double>( 1.0 ); // prints "b"
          foo( 1 );           // prints "a"
      }
      

      为什么foo<int>( 1 )为什么打印"b"而不打印"a"?

      Why does foo<int>( 1 ) print "b" and not "a"?

      wandbox示例

      推荐答案

      基本上,部分排序规则认为dependent_type重载由于其非推论上下文而更加专门化.

      Essentially the partial ordering rules say that the dependent_type overload is more specialized because of that non-deduced context.

      对模板函数进行排序的过程是基于变换模板函数类型并依次对每种模板进行演绎,一次是从第一个模板(一个采用T的模板)转到第二个模板(采用dependent_type的模板). ),然后从第二个到第一个.

      The process for ordering template functions is based on transforming the template function types and performing template deduction on each in turn, once going from the first template (the one taking T) to the second (the one taking dependent_type), then from the second to the first.

      规则太复杂,无法在此处复制,但请阅读 [temp.func.order] 及其链接的段落,以获取详细信息.这是一个快速的简化:

      The rules are far too complex to replicate here, but go read [temp.func.order] and the passages it links to if you want the gory details. Here's a quick simplification:

      对于模板函数的每个模板参数,请组成一个唯一的类型,然后用该参数替换该参数.此示例的转换类型为:

      For each template parameter of the template function, make up a unique type and replace the parameter with that. The transformed types for this example are:

      void foo(UniqueType); //ignoring the SFINAE for simplicity
      void foo(typename dependent_type<UniqueType>::type); 
      

      然后我们在两个方向上执行模板推导:一次将第一个模板的参数用作第二个的参数,一次将第二个模板的参数用作第一个的参数.这类似于对这些函数调用执行推论:

      We then perform template deduction in two directions: once using the parameters of the first template as arguments to the second, and once using the parameters of the second as arguments to the first. This is akin to performing deduction on these function calls:

      //performed against template <class T> void foo(typename dependent_type<T>::type);
      foo(UniqueType{});                     
      
      //performed against template <class T> void foo(T);        
      foo(dependent_type<UniqueType>::type{});
      

      在进行这些推论时,我们试图辨别一个过载是否比另一个过载更专业.当我们尝试第一个时,推论失败,因为typename dependent_type<T>::type是一个非推论上下文.对于第二个,推导成功,因为dependent_type<UniqueType>::type只是UniqueType,所以T被推导为UniqueType.

      In carrying out these deductions, we're trying to discern whether one overload is more specialized then the other. When we try the first one, deduction fails, since typename dependent_type<T>::type is a non-deduced context. For the second one, deduction succeeds because dependent_type<UniqueType>::type is just UniqueType, so T is deduced to UniqueType.

      由于从第二个模板到第一个模板的推导失败,因此第二个模板被认为比第一个模板更专业.最终结果是,重载分辨率优先使用foo<int>(1)的第二个模板.

      Since deduction failed going from the second template to the first, the second template is taken as being more specialized than the first. The final result is that the overload resolution prefers the second template for foo<int>(1).

      这篇关于用`std :: enable_if`和非推导上下文重载函数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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