decltype 在模板参数推导失败的地方成功?
decltype succeeds where template argument deduction fails?
我想知道为什么当带有 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)
只需要推导一对parameter/argument。 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&
,但不是因为它是这样推导出来的——因为它被替换了。
我想知道为什么当带有 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)
只需要推导一对parameter/argument。 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&
,但不是因为它是这样推导出来的——因为它被替换了。