标准库实现是否可以具有与C ++标准不同的类定义? [英] Is it permissible for standard library implementation to have class definition that is different from the C++ standard?

查看:99
本文介绍了标准库实现是否可以具有与C ++标准不同的类定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码已使用clang和MSVC成功编译,但无法在GCC 6.1.0中编译.

The following code successfully compiled with clang and MSVC but fail to compile in GCC 6.1.0.

#include <memory>

template<typename R, typename T, typename... Args>
T* test(R(T::*)(Args...) const)
{
    return nullptr;
}

int main()
{
    using T = std::shared_ptr<int>;
    T* p = test(&T::get);
}

并显示以下错误消息

prog.cc: In function 'int main()':
prog.cc:13:16: error: invalid conversion from 'std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2u>*' to 'T* {aka std::shared_ptr<int>*}' [-fpermissive]
     T* p = test(&T::get);
            ~~~~^~~~~~~~~

问题在于libstdc ++是通过从基类std::__shared_ptr继承成员函数get来实现std::shared_ptr的.

The problem is that libstdc++ implemented std::shared_ptr by inheriting member function get from a base class std::__shared_ptr.

在C ++标准 20.8.2.2类模板shared_ptr 中,它使用该类的所有成员函数指定std :: shared_ptr类的类定义.

In the C++ standard 20.8.2.2 Class template shared_ptr, it specifies the class definition of std::shared_ptr class with all the member functions of that class.

我的问题是,实现是否必须至少提供标准类内部标准中定义的所有公共类成员?是否可以通过继承libstdc ++中实现的基类来提供成员函数?

My question is whether the implementation must at least provide all public class members as defined in the standard inside the standard class? Is it allowed to provide the member functions by inheriting from base class as implemented in libstdc++?

推荐答案

除非特别说明,否则类型及其成员的标准规范是规范性文本.因此,在某种程度上,要求实施者遵循该标准,以使其遵循标准中的任何内容.

The standard's specification for types and their members is normative text, unless it explicitly says otherwise. As such, an implementation is required to follow that... to the extent that an implementation is required to follow anything from the standard.

这个范围就是好像"规则.即,只要类型的行为好像"按照指定完成,就允许该实现执行所需的操作.该标准使用特定的语言来说明类型可以从任意的,实现提供的基类中派生的原因是,这是用户可以检测到的.这是可见的行为(通过隐式转换等),因此该标准必须允许例外.

And that extent is the "as if" rule. Namely, the implementation is allowed to do what it wants so long as the type behaves "as if" it were done as specified. The reason the standard has specific language stating that types can be derived from arbitrary, implementation-provided base classes is because that is something which a user can detect. It's visible behavior (through implicit conversions and the like) and therefore the standard would have to make an exception in order to allow for it.

继承成员几乎与在主类中声明成员一样.确实,我知道区别的唯一方法是执行此处所做的操作:使用模板参数推导规则.即使您可以将成员指定为Derived::get,但是如果它确实来自某个基类,编译器也会知道.

Inheriting a member is almost the same thing as declaring it in your main class. Indeed, the only way I know of to tell the difference is to do what you did here: use template argument deduction rules. Even though you can specify the member as Derived::get, if it really comes from some base class, the compiler will know.

但是,[member.functions]在这里为GCC提供了帮助.它具有显式语言,允许标准库实现向类添加其他重载.因此,您在此处使用std::shared_ptr<int>::get的行为不是明确定义的.的确,脚注187对此做了澄清:

However, [member.functions] comes to GCC's rescue here. It has explicit language allowing standard library implementations to add additional overloads to a class. Because of that, your use of std::shared_ptr<int>::get here is not well-defined behavior. Indeed, footnote 187 clarifies this:

因此,C ++标准库中类的成员函数的地址具有未指定的类型.

Hence, the address of a member function of a class in the C++ standard library has an unspecified type.

这只是一个脚注,但目的似乎很明确:您不能依赖任何特定的实现来返回任何特定类型的成员指针.即使您对正确的签名应用了强制转换操作,也无法保证它会起作用.

That's merely a footnote, but the intent seems clear: you cannot rely on any particular implementation to return any particular type of member pointer. Even if you applied a cast operation to the right signature, there is no guarantee that it would work.

因此,尽管标准库中的类定义是标准文本,但是[member.functions]清楚地表明,您可以保证有关这些定义的 only 事情是您可以使用提供的参数.其他任何事情,例如获取成员指针,都是实现定义的.

So while the class definition in the standard library is normative text, [member.functions] makes it clear that the only thing you can guarantee about those definitions is that you can call those functions using the arguments provided. Anything else, like getting member pointers, is implementation-defined.

这篇关于标准库实现是否可以具有与C ++标准不同的类定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆