隐式转换可能在模板替换期间发生

Implicit conversion may happen during template substitution?

本文关键字:替换 转换      更新时间:2023-10-16

我一直认为,对于模板化的函数,不可能发生隐式转换,实参的类型必须与模板化的形参类型完全匹配,否则模板实参推导将失败。

好吧,看来我错了。

考虑以下代码片段:

#include <iostream>
#include <type_traits>
template <class T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
class myInt
{
    T val;
public:
    myInt(T val) : val(val) {}
    template <class U, typename = typename std::enable_if<std::is_integral<U>::value>::type>
    friend bool operator < (myInt<T> const &t, myInt<U> const &u)
    {
        return t.val < u.val;
    }
};
int main()
{
    myInt<int> i = 5;
    myInt<int> j = 6;
    // std::cout << (i < 6) << std::endl; // gives out compiler errors
    std::cout << (5 < j) << std::endl; // works!
}

我不知道为什么第二个std::cout << (5 < j)工作。这里肯定发生了隐式转换,我以为这是被禁止的。我更不确定为什么如果前者可以,std::cout << (i < 6)就不能工作!

编辑:std::cout << (i < 6)编译错误:

test.cpp: In function ‘int main()’:
test.cpp:23:21: error: no match for ‘operator<’ (operand types are ‘myInt<int>’ and ‘int’)
     std::cout << (i < 6) << std::endl; // gives out compiler errors
                     ^
test.cpp:23:21: note: candidate is:
test.cpp:12:17: note: template<class U, class> bool operator<(const myInt<int>&, const myInt<T>&)
     friend bool operator < (myInt<T> const &t, myInt<U> const &u)
                 ^
test.cpp:12:17: note:   template argument deduction/substitution failed:
test.cpp:23:23: note:   mismatched types ‘const myInt<T>’ and ‘int’
     std::cout << (i < 6) << std::endl; // gives out compiler errors

这是"不对称"的原因是UT在这方面有根本的区别:

template <class U, typename =
          typename  std::enable_if<std::is_integral<U>::value>::type>
friend bool operator < (myInt<T> const &t, myInt<U> const &u);

operator<为模板,U为该模板的参数。但是T不是这个模板的参数。T实际上是另一个模板myInt的参数,因此在这个上下文中是固定的(为T=int)。

实际上是这样的:

template <class U, /*SFINAE stuff*/>
friend bool operator < (myInt<int> const &t, myInt<U> const &u);

给定(5 < j),它知道如何将5转换为tmyInt<int> const &。通过推断U = ' int.

,它可以很容易地将j (myInt<int>)传递给myInt<U> const &u

但是(j<6)不会工作,因为它不知道如何将6传递给template<class U> ..... myInt<U> const &u。特别是,它如何猜测哪个U将使用必要的构造函数创建合适的myInt<U> ?也许myInt<int>string构造函数,而myInt<string>int构造函数!编译器不能知道。


我认为你可以这样做:

/*   *NOT* a template */
friend bool operator < (myInt<T> const &t, myInt<T> const &u);
                         T instead of U ~~~~~~~~~^