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

时间:2015-08-07 10:17:04

标签: c++ template-deduction

我一直认为使用模板化函数时,不会发生隐式转换,参数类型必须与参数的模板化类型完全匹配,否则模板参数推断将失败。

嗯,好像我错了。

请考虑以下代码段:

#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

1 个答案:

答案 0 :(得分:2)

这是&#34; assymetrical&#34;这是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转换为myInt<int> const & t。通过推断j =`int,它可以轻松地将myInt<int>(a myInt<U> const &u)传递给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 ~~~~~~~~~^