1

我想知道为什么当带有 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";
}
4

1 回答 1

3

当你这样做时:

template<class T> 
bool isEqual(T const& a, T const& b)

Ts 推断为不同的类型(forStringafor Personb。由于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&,但不是因为它是这样推导的 - 因为它被替换了。

于 2015-08-14T18:18:57.333 回答