我想知道为什么以下代码在未注释掉带有bbb的行但在其前面的行时能按预期的方式编译和运行,但是当未注释掉以aaa标记的行和bbb行时,它的确会失败是:
#include <iostream>
#include <string>
using String = std::string;
struct Person {
String m_name;
explicit Person(String const &name): m_name(name) {}
operator String() const { return "\"" + m_name + "\""; }
};
template<class T> bool isEqual(
T const& a,
//T const& // does NOT compile // aaa
decltype(a) // DOES compile // bbb
b){ return a == b; }
int main()
{
String const plain("plain");
Person const jb("James");
bool b = isEqual(plain, jb);
std::cout << "isEqual(plain, person) is " << ( b ? "true" : "false" ) << "\n";
}
最佳答案
当您这样做时:
template<class T>
bool isEqual(T const& a, T const& b)
T
推断为不同的类型(String
的a
和Person
的b
)。由于T
只能是一种类型,因此推论失败。但是,当您这样做时:
template<class T>
bool isEqual(T const& a, decltype(a) b)
只需要推导一个参数/参数对。
T
被推导为String
,并且由于Person
可以转换为String
(通过转换函数operator String()
),因此可以正常工作。这类似于
identity
技巧,在该技巧中,我们仅强制一个参数处于非推导上下文中:template <typename T>
struct identity { using type = T; };
template <typename T>
bool isEqual(T const& a, typename identity<T>::type const& b);
同样,只有一对发生类型推导,
T
推导为String
-因此b
的类型也为String const&
,但不是因为它是这样推导的-因为它被替换了。关于c++ - 如果模板参数推导失败,则decltype成功?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32016342/