我想知道为什么以下代码在未注释掉带有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推断为不同的类型(StringaPersonb)。由于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/

10-11 00:50