标准库实现是否允许与C标准不同的类定义?

以下代码使用clang和MSVC成功编译,但在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的基类获取std :: shared_ptr.

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

我的问题是,实现是否至少提供标准类标准中定义的所有公共类成员?是否允许通过继承libstdc中实现的基类来提供成员函数?

最佳答案
标准的类型及其成员的规范是规范性文本,除非另有明确说明.因此,需要实施这样一个实现,以便实施需要遵循标准中的任何内容.

那个程度就是“好像”的规则.也就是说,只要类型按照指定的方式行事,就可以执行所需的工作.标准具有特定语言的原因是,可以从任意的,实现提供的基类派生类型,因为这是用户可以检测的东西.它是可见的行为(通过隐式转换等),因此标准将不得不作出异常以允许它.

继承一个成员几乎和你的主类中声明的一样.事实上,我唯一知道的区别就是做你在这里做的:使用模板参数扣除规则.即使您可以将成员指定为Derived :: get,如果它真的来自某些基类,编译器也会知道.

然而,[会员]功能来到海合会在这里的救援.它具有明确的语言,允许标准库实现向类添加额外的重载.因为这样,你使用std :: shared_ptr< int> :: get这里并不是很明确的行为.事实上,脚注187澄清了这一点:

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

这只是一个脚注,但意图似乎很清楚:您不能依赖任何特定的实现来返回任何特定类型的成员指针.即使您将投标操作应用于正确的签名,也不能保证它能正常工作.

因此,虽然标准库中的类定义是规范性文本,[member.functions]清楚地表明,您可以为这些定义唯一保证的是可以使用提供的参数调用这些函数.其他任何东西,如获取成员指针,都是实现定义的.

转载注明原文:标准库实现是否允许与C标准不同的类定义? - 代码日志