使用现代C++时,具有私有构造函数的类的std :: vector无法编译

pup*_*162 13 c++ c++17

我正在处理的代码最初设计使用C++03,编译和功能没有错误使用g++ -std=c++03.我的目标是使用相同的代码编译g++ -std=c++17.

该代码包含一个MyClass包含a 的代码NestedClass.只MyClass应该能够使用,创建和修改NestedClass存储在a中的实例std::vector< NestedClass >.因此NestedClass包含私有构造函数,并声明MyClassstd::vector< NestedClass >作为朋友.

最小例子:

#include <vector>

class MyClass {

    public:

        class NestedClass {
            friend class MyClass;
            friend class std::vector< NestedClass >;
            double _d;
            NestedClass( double d = 0.0 ) : _d(d){ }
        };

    private:

        std::vector< NestedClass > data;

    public:

        MyClass(){
            data.resize( 40 );
        }


};

int main(){
    MyClass myclass = MyClass();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译-std=c++17时出现以下错误,此最小示例失败:

/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = MyClass::NestedClass; _Args = {}]’:
/usr/include/c++/7/bits/stl_uninitialized.h:527:18:   required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = MyClass::NestedClass*; _Size = long unsigned int; bool _TrivialValueType = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:583:20:   required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = MyClass::NestedClass*; _Size = long unsigned int]’
/usr/include/c++/7/bits/stl_uninitialized.h:645:44:   required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = MyClass::NestedClass*; _Size = long unsigned int; _Tp = MyClass::NestedClass]’
/usr/include/c++/7/bits/vector.tcc:563:35:   required from ‘void std::vector<_Tp, _Alloc>::_M_default_append(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MyClass::NestedClass; _Alloc = std::allocator<MyClass::NestedClass>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/7/bits/stl_vector.h:692:21:   required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = MyClass::NestedClass; _Alloc = std::allocator<MyClass::NestedClass>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
bug.cpp:21:20:   required from here
/usr/include/c++/7/bits/stl_construct.h:75:7: error: ‘MyClass::NestedClass::NestedClass(double)’ is private within this context
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bug.cpp:11:4: note: declared private here
    NestedClass( double d = 0.0 ) : _d(d){ }
Run Code Online (Sandbox Code Playgroud)

如何重写代码以便使用c ++ 17进行编译?

更改std::vector< NestedClass >std::vector< NestedClass * >是不是因为它需要使用重写代码的选项MyClass,我无法控制.

T.C*_*.C. 13

您的特定示例的简约修复是

data.resize( 40, {} );
Run Code Online (Sandbox Code Playgroud)

自己调用私有构造函数,这样vector只需要调用(隐式声明的)公共构造函数.


一般来说,在你无法控制的图书馆里交朋友是行不通的.你不知道是否说某事实际上是将工作委托给其他人.

vector这种情况下,几乎需要将所述工作委托给其他人.


适当的修复可能涉及对所涉及的类的更改.一种可能性是密钥习语:使构造函数公开,但只能使用私有类型的参数调用.