代码之家  ›  专栏  ›  技术社区  ›  user4992621

模板参数推导失败时decltype成功?

  •  1
  • user4992621  · 技术社区  · 9 年前

    我想知道为什么当带有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";
    }
    
    1 回复  |  直到 9 年前
        1
  •  3
  •   Barry    9 年前

    当您这样做时:

    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 被推断为 一串 ,自 可以转换为 一串 (通过转换功能 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 推断为 一串 -因此 b 也是 String const& ,但不是因为它是这样推断的,因为它在中被替换了。