【发布时间】:2016-10-27 07:40:00
【问题描述】:
以下代码使用 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 继承成员函数 get 来实现 std::shared_ptr。
在C++标准20.8.2.2类模板shared_ptr中,它指定了std::shared_ptr类的类定义以及该类的所有成员函数。
我的问题是,实现是否必须至少在标准类内部提供标准中定义的所有公共类成员?是否允许通过从libstdc++中实现的基类继承来提供成员函数?
【问题讨论】:
-
17.6.5.11 派生类 [派生] 实现可以从一个为实现保留名称的类派生 C++ 标准库中的任何类。脚注 188 (n3797) 可能也很有趣。
-
Hmya,您也不会在标准中找到 Lock_policy 模板参数。当编译器库编写者在标准获得批准之前实现一个类或使其适用于现实世界时,就会发生这种情况。在标准中不包括锁定策略是一个颇具争议的决定。现实世界覆盖。
-
我不太擅长阅读标准。我对这句话的理解是允许实现从基类继承,但没有指定是否允许/不允许通过从基类继承来提供标准类中的类成员函数。
-
问题是编译器出错了。
std::shared_ptr<int>::get是std::shared_ptr<Int>的成员函数,不管它是如何到达那里的,而模板中的T是std::shared_ptr<int>。 -
我认为实现提供额外的构造函数或方法以及实现从隐藏类派生是可以的,但实现的标准类至少应该具有标准中定义的所有公共成员。如果标准说
shared_ptr类定义中有一个get成员,我可以期望正确的行为能够编译上面的代码吗?
标签: c++ language-lawyer c++-standard-library