【问题标题】:Are these two types the same types of not? [duplicate]这两种类型是同一种类型吗? [复制]
【发布时间】:2021-08-13 19:22:26
【问题描述】:

我对我写的这个模板感到很困惑,它应该“自动”推断出我​​传入的指针类型,但编译器似乎并不认为这两种类型是相同的,而我却认为,并且typeid() 在我身边。

#include <iostream>

template <auto* static_ptr_to_object>
struct Handle
{
    // static_ptr_to_object should be a pointer to a Whale<char>
    // Both of the following typedefs should result in types of Whale<char>
    // When I cout typeid() of these types it prints out the same types
    // However std::is_same_v returns false

    using pointee_type1 = std::remove_pointer_t<decltype(static_ptr_to_object)>;
    using pointee_type2 = decltype(*static_ptr_to_object); // The two are the same types

    void showTypes()
    {
        //static_assert(std::is_same_v<pointee_type1, pointee_type2>);
        // Uncommenting this line will make the static assert fail

        std::cout << "Type of 'pointee_type1' = " << typeid(pointee_type1).name() << "\n";
        std::cout << "Type of 'pointee_type2' = " << typeid(pointee_type2).name() << "\n";

        if (typeid(pointee_type1) == typeid(pointee_type2))
            std::cout << "Types are the same\n";
        else std::cout << "Types are not the same\n";

    }

    bool b1 = std::is_integral_v<decltype(pointee_type1::member)>;
    // Uncommenting the below line will make compilation fail

    //bool b2 = std::is_integral_v<decltype(pointee_type2::member)>;
    // pointee_type2 must be a class or namespace when followed by ::
    // pointee_type2 left of '::' must be a class or namespace name
    

};

template <typename T>
struct Whale
{
    T member;
};

Whale<char> whale;

int main()
{
    Handle<&whale> handleToWhale;
    handleToWhale.showTypes();
}

所以我认为这两种类型是相同的,typeid() 运算符表示它们是相同的,但std::is_same 返回false,并且根据编译器错误消息它无法识别pointee_type2 是类类型,因为它无法识别 :: 运算符。

编辑:我对解除引用指针的理解是错误的,this question relates to 在某些情况下指针解除引用将如何返回引用类型。

【问题讨论】:

标签: c++ c++11 templates decltype typeid


【解决方案1】:

对于decltype

  1. 如果参数是不带括号的 id 表达式或不带括号的类成员访问表达式,则 decltype 产生由该表达式命名的实体的类型。 ......

  2. 如果参数是任何其他类型 T 的表达式,并且

    a) ...
    b) 如果表达式的值类别是左值,则 decltype 产生 T&;
    c) ...

*static_ptr_to_object 适合第二种情况,它是一个左值表达式,所以decltype(*static_ptr_to_object) 产生一个引用类型,即Whale&lt;char&gt;&amp;pointee_type1pointee_type2 不是同一个类型。

您可以使用std::remove_reference 获得与以下相同的类型:

using pointee_type2 = std::remove_reference_t<decltype(*static_ptr_to_object)>;

另一方面,typeid 确实产生相同的结果(相同的 std::type_info 对象)。

如果 type 是引用类型,则结果引用表示被引用类型的 std::type_info 对象。

【讨论】:

  • 所以它不是一个模板的东西,解引用一个指针会给你一个指向它所指向的任何东西的引用,并且任何被解引用的指针的 decltype 都将是一个指向任何类型的引用?
  • @Zebrafish decltype 以两种不同的方式工作。对于 id-expression,它产生由 id-expression 命名的实体的确切类型。对于其他表达式,它不仅根据表达式的类型,还根据表达式的值类别给出结果。如果指针的取消引用导致左值表达式,那么您将得到T&amp;
【解决方案2】:

pointee_type1Whale&lt;char&gt;,但 pointee_type2Whale&lt;char&gt; &amp;typeid 删除引用,所以你得到相同的名称。

【讨论】:

    猜你喜欢
    • 2018-10-29
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 2019-12-04
    • 2016-09-20
    相关资源
    最近更新 更多