简体   繁体   English

如果两者都可行,编译器如何确定使用 SFINAE 的函数和标准函数?

[英]How does the compiler determine between a function using SFINAE and a standard function if both are viable?

Consider the following code:考虑以下代码:

#include <iostream>
#include <type_traits>

template <typename T>
class A
{
public:
    // Allow func to be called if T is the const version of T2
    // e.g., T is 'int const' and T2 is 'int'
    template <typename T2,
              typename = typename std::enable_if<
                                          std::is_same<T, T2 const>::value>::type>
    void func(A<T2> const &)
    {
        std::cout << "Conversion" << std::endl;
    }

    // Allow func to be called for same version of T
    void func(A const &)
    {
        std::cout << "No conversion" << std::endl;
    }
};

int main()
{
    A<int const> a;

    a.func(A<int const>{});

    return 0;
}

This code, when compiled with GCC-8.3 compiles and produces the output No conversion - it selected the version of func that does not use std::enable_if .此代码在使用 GCC-8.3 编译时编译并产生输出No conversion - 它选择了不使用std::enable_iffunc版本。 However, if I comment out the second version of func , it will still compile and now produce the output Conversion .但是,如果我注释掉func的第二个版本,它仍然会编译并现在生成输出Conversion In other words, both versions of func within A are usable for this method.换句话说, A中的两个版本的func都可用于此方法。 Given that both overloads are viable, what specific rule is the compiler using to select func(A const &) over the other version ( func(A<T2> const &) )?鉴于两个重载都是可行的,编译器使用什么特定规则来选择func(A const &)而不是另一个版本( func(A<T2> const &) )?

The rule is that if a non function template and a function template specialization have the same signature, then the non function template is chosen over the template specialization.规则是,如果非函数模板和函数模板特化具有相同的签名,则选择非函数模板而不是模板特化。 This can be found in [over.match.best]/2这可以在[over.match.best]/2 中找到

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then鉴于这些定义,如果对于所有参数 i,ICSi(F1) 不是比 ICSi(F2) 更差的转换序列,那么一个可行函数 F1 被定义为比另一个可行函数 F2 更好的函数,然后

[...] [...]

  • F1 is not a function template specialization and F2 is a function template specialization [...] F1 不是函数模板特化,F2 是函数模板特化 [...]

You can read about overload resolution here .您可以 在此处阅读有关重载解析的 信息 In particular特别是

If any candidate is a function template, its specializations are generated using template argument deduction, and such specializations are treated just like non-template functions except where specified otherwise in the tie-breaker rules.如果任何候选函数是函数模板,则使用模板参数推导生成其特化,并且此类特化被视为非模板函数,除非在决胜局规则中另有规定。

And then进而

Best viable function最佳可行功能

For each pair of viable function F1 and F2, the implicit conversion sequences from the i-th argument to i-th parameter are ranked to determine which one is better [...]对于每对可行函数 F1 和 F2,从第 i 个参数到第 i 个参数的隐式转换序列被排序以确定哪个更好 [...]

F1 is determined to be a better function than F2 if implicit conversions for all arguments of F1 are not worse than the implicit conversions for all arguments of F2, and [...]如果 F1 的所有参数的隐式转换不比 F2 的所有参数的隐式转换差,则确定 F1 是比 F2 更好的函数,并且 [...]

4) [...] F1 is a non-template function while F2 is a template specialization 4) [...] F1 是非模板函数,而 F2 是模板特化

Basically the same rules apply in this simpler example:基本上相同的规则适用于这个更简单的例子:

#include<iostream>

template <typename T> 
void foo(T i) { std::cout << "template" ; }

void foo(int i) { std::cout << "non template"; }

int main() {
    foo(1);   // non template
}

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

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