Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否允许标准库实现具有不同于C+的类定义+;标准_C++_Language Lawyer_C++ Standard Library - Fatal编程技术网

C++ 是否允许标准库实现具有不同于C+的类定义+;标准

C++ 是否允许标准库实现具有不同于C+的类定义+;标准,c++,language-lawyer,c++-standard-library,C++,Language Lawyer,C++ Standard Library,以下代码使用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(&a

以下代码使用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);
}
#包括
模板
T*测试(R(T::*)(Args…)常数)
{
返回空ptr;
}
int main()
{
使用T=std::shared_ptr;
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);
            ~~~~^~~~~~~~~
prog.cc:在函数“int main()”中:
程序cc:13:16:错误:从“std::_shared_ptr*”到“T*{aka std::shared_ptr*}”[-fppermissive]的转换无效
T*p=test(&T::get);
~~~~^~~~~~~~~
问题是libstdc++通过从基类
std:\uuuu-ptr
继承成员函数
get
实现了
std::shared\u-ptr

在C++标准>强> 20.82.2类模板SysDypPTR<强>中,它指定了具有该类的所有成员函数的STD::SydDypTr类的类定义。


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

标准的类型及其成员规范为规范性文本,除非另有明确说明。因此,需要执行以下操作。。。在某种程度上,实现需要遵循标准中的任何内容

而这种程度就是“似乎”规则。也就是说,只要类型的行为“好像”是按照指定的方式完成的,就允许实现做它想做的事情。该标准使用特定语言声明类型可以从任意实现提供的基类派生,这是因为用户可以检测到这一点。它是可见的行为(通过隐式转换等),因此标准必须做出例外才能允许它

继承成员与在主类中声明成员几乎是一样的。事实上,我所知道的辨别差异的唯一方法就是执行您在这里所做的操作:使用模板参数推断规则。即使您可以将成员指定为
派生::get
,如果它确实来自某个基类,编译器也会知道

然而,[member.functions]在这里拯救了GCC。它有明确的语言,允许标准库实现向类添加额外的重载。因此,您在此处使用
std::shared_ptr::get
不是定义良好的行为。事实上,脚注187澄清了这一点:

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

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


因此,尽管标准库中的类定义是规范性文本,[member.functions]明确指出,对于这些定义,您唯一可以保证的是,您可以使用提供的参数调用这些函数。任何其他的,比如获得成员指针,都是实现定义的。

7.65.11派生类[派生]。一个实现可以从C++中的任何类库中派生出一个类,该类的名称保留给实现。脚注188(n3797)可能也很有趣。嗯,在标准中也找不到Lock_策略模板参数。当编译器库编写者要么在标准被批准之前实现一个类,要么将其用于实际使用时,就会发生这种情况。在标准中不包含锁定策略是一个颇具争议的决定。现实世界中的凌驾。我不太擅长阅读标准。我对这句话的理解是,允许实现从基类继承,但它没有指定是否允许/不允许通过从基类继承在标准类中提供类成员函数。问题是编译器是错误的
std::shared_ptr::get
std::shared_ptr
的成员函数,无论它是如何到达的,模板中的
T
std::shared_ptr
。我认为实现可以提供额外的构造函数或方法,实现可以从隐藏类派生,但实现的标准类至少应该在标准中定义所有公共成员。如果标准规定在
shared_ptr
类定义中有
get
成员,我能期望正确的行为能够编译上述代码吗?我认为脚注187应该在[member.function]2和(2.1)的上下文中阅读。2.一个实现可以在一个类中声明额外的非虚拟成员函数签名:(2.1)-通过向成员函数签名添加带有默认值的参数;187我的理解是,实现可以提供成员函数
void get(int=0)
;如果std指定成员函数
void get()
,则脚注187澄清未指定成员get的类型。它可以是
void(T::*)(int)
void(T::*)()
,但它不是必须仍在类中吗?如果上面的测试函数返回
sizeof(Args…
,则脚注187将其定义为实现。@kwanti:脚注没有说明签名是实现定义的;因为这是唯一的答案,我会接受它(谢谢你的回答)。令人难以置信的是,标准告诉我们不能将标准类的成员函数指针用于任何事情,因为我们不知道它的类型。我说这意味着如果我