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

时间:2018-07-03 08:25:30

标签: c++ c++17

我正在使用的代码最初是使用C++03设计的,并使用g++ -std=c++03进行了编译和生成函数而没有错误。我的目标是使用g++ -std=c++17编译相同的代码。

该代码包含一个MyClass,其中包含一个NestedClass。只有MyClass才能使用,创建和修改NestedClass的实例,这些实例存储在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;
}

在编译-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){ }

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

std::vector< NestedClass >更改为std::vector< NestedClass * >并不是一种选择,因为它将需要重写使用MyClass的代码,而我无法控制这些代码。

1 个答案:

答案 0 :(得分:13)

您的特定示例的最低要求是

data.resize( 40, {} );

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


通常,与您无法控制的库中的某些内容成为好友是行不通的。您不知道是否所说的话实际上会将工作委托给其他人。

vector的情况下,非常需要将所述工作委派给其他工作。


适当的修复可能会涉及对涉及的类进行更改。密码成语是一种可能:使构造函数公开,但只能使用私有类型的参数来调用。