简体   繁体   English

如何使用朋友访问STL私人成员

[英]How to use friend to access STL private member

When I do this... 当我这样做时...

auto t = typeid(float);

... I get: ...我得到:

Error C2248 'type_info::type_info': cannot access private member declared in class 'type_info' 错误C2248'type_info :: type_info':无法访问在类'type_info'中声明的私有成员

Of course, I know I can do this... 当然,我知道我可以做到...

auto t = typeid(float).name();

But if I wanted to use the first expression, how would I go about tampering with the type_info class and using friend to achieve my objective? 但是,如果我想使用第一个表达式,我该如何篡改type_info类并使用friend来实现我的目标? Any suggestions? 有什么建议么?

You can't make your class a friend of a standard class. 您不能让您的班级成为标准班级的friend

A typeid expression is an lvalue, so you can simply bind a reference to it: 一个typeid表达式是一个左值,因此您可以简单地将引用绑定到它:

auto& t = typeid(float);

The reason you cannot do this is the copy constructor and the assignment operator of std::type_info are marked as delete per [type.info]. 您无法执行此操作的原因是复制构造函数,并且std::type_info的赋值运算符被标记为每个[type.info]的delete So 所以

auto t = typeid(float);

Will attempt to call the copy constructor which will fail. 将尝试调用将失败的复制构造函数。

As TartanLlama points out in his answer you can capture a reference to it with 正如TartanLlama在他的回答中指出的那样,您可以使用

auto& t = typeid(float);
 Error C2248 'type_info::type_info': cannot access private member declared in class 'type_info' 

This error message refers to the copy constructor of type_info which you've tried to invoke with auto t = typeid(float); 此错误消息引用了您尝试使用auto t = typeid(float);调用的type_info的副本构造函数auto t = typeid(float); .

But if I wanted to use the first expression, how would I go about tampering with the type_info class and using friend to achieve my objective? 但是,如果我想使用第一个表达式,我该如何篡改type_info类并使用friend来实现我的目标? Any suggestions? 有什么建议么?

Even if you could manipulate type_info 's definition, which you cannot , what would you possibly do? 即使您可以操纵type_info的定义(您也无法做到),您可能会怎么做? The copy constructor is not private because it needs to be hidden from you but because the language does not define what it means to copy a type_info . 复制构造函数不是私有的,因为它需要向您隐藏,但因为该语言未定义复制type_info含义。 In fact, even if you somehow declared the member function as public (which is already purely hypothetical), there would be no definition and thus a linker error. 实际上,即使您以某种方式将成员函数声明为public函数(这已经纯粹是假设的),也没有定义,因此也就没有链接器错误。

I don't know why GCC is not more specific in its error message here. 我不知道为什么GCC在这里的错误消息中没有更具体。 With C++11, the copy constructor is not just private but deleted and that's the reason it cannot be used. 使用C ++ 11时,复制构造函数不仅是private而且已删除 ,这就是不能使用它的原因。 Coincidentally, MSVC's error message is more appropriate, as it says: 碰巧的是,MSVC的错误消息更合适,因为它说:

error C2280: 'type_info::type_info(const type_info &)' : 
attempting to reference a deleted function

A modern C++11 solution to your problem is to use std::type_index , which is a copyable wrapper around std::type_info . 解决问题的现代C ++ 11解决方案是使用std::type_index ,它是std::type_info周围的可复制包装器。 Here is an example: 这是一个例子:

#include <typeindex>

int main()
{
    auto t = std::type_index(typeid(float));
}

Class std::type_info has deleted copy constructor. std::type_info已删除副本构造函数。

type_info(const type_info& rhs) = delete; // cannot be copied
                                  ^^^^^^^^ 

On the other hand (5.2.8 Type identification) 另一方面(5.2.8类型识别)

1 The result of a typeid expression is an lvalue of static type const std::type_info (18.7.1) and dynamic type const std::type_info or const name where name is an implementation-defined class publicly derived from std :: type_info which preserves the behavior described in 18.7.1.69 The lifetime of the object referred to by the lvalue extends to the end of the program . 1 typeid表达式的结果是静态类型const std :: type_info(18.7.1)和动态类型const std :: type_info或const name 的左值 ,其中name是从std :: type_info公开派生的实现定义的类,保留18.7.1.69中描述的行为。lvalue 引用的对象的生存期延长到程序的结尾 Whether or not the destructor is called for the std::type_info object at the end of the program is unspecified. 程序末尾是否为std :: type_info对象调用析构函数是不确定的。

So you can write for example 所以你可以写例如

#include <iostream>

int main()
{
    decltype( auto ) t = typeid( float );

    std::cout << t.name() << std::endl;

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM