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

戏子无情 提交于 2020-06-22 03:25:48

问题


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. However, if I comment out the second version of func, it will still compile and now produce the output Conversion. In other words, both versions of func within A are usable for this method. 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 &))?


回答1:


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

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

[...]

  • F1 is not a function template specialization and F2 is a function template specialization [...]



回答2:


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 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 [...]

4) [...] F1 is a non-template function while F2 is a template specialization

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
}


来源:https://stackoverflow.com/questions/60328852/how-does-the-compiler-determine-between-a-function-using-sfinae-and-a-standard-f

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!