这是类的简化版本,它作为值存储在一个在VS2008中正常工作的 Map 中(注意 all 成员是私有的):
class Value{
friend class FriendClass;
friend class std::map<std::string, Value>;
friend struct std::pair<const std::string, Value>;
friend struct std::pair<std::string, Value>;
Value() {..}
Value(Value const& other) {..}
... rest members...
};
代码(从FriendClass调用,因此可以访问私有构造函数):
FriendClass::func()
{
std::map<const std::string, Value> map;
map.insert(std::make_pair(std::string("x"), Value()));
}
这不会编译VS2008中的任何错误,但在VS2015 / C 11上失败:
file.cpp(178): error C2664: 'std::_Tree_iterator>>> std::_Tree>::insert(std::_Tree_const_iterator>>>,const std::pair &)': cannot convert argument 1 from 'std::pair' to 'std::pair &&'
with
[
_Kty=std::string,
_Ty=Value,
_Pr=std::less,
_Alloc=std::allocator>
]
and
[
_Kty=std::string,
_Ty=Value
]
file.cpp(178): note: Reason: cannot convert from 'std::pair' to 'std::pair'
with
[
_Kty=std::string,
_Ty=Value
]
file.cpp(178): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
如果我将Value复制构造函数设置为public,它在VS2015中编译也很好 .
但这是有目的的私有,只有std :: map和std :: pair可用 . 但是,似乎在C 11中额外的朋友访问也需要申报 . 这些是哪些?
谢谢 .
1 回答
我没有访问你提到的编译器,但这是我在g 5.3上看到的 .
请考虑以下基本相同版本的问题:
(默认的ctor是
public
,但这不是必需的,只是缩短了示例 . )在
main
中,请注意两行反转注释构建正常,但显示的版本不是:
查看源代码
std_pair.h
表明它确实在尝试调用复制构造函数 . 不幸的是,你friend
edstd::pair
,但不是std::make_pair
.emplace
版本没有这个问题,但我怀疑这是依赖于实现的 . 通常,如果您希望容器存储完全不透明的类,我建议您使用std::shared_ptr
的容器 . 这允许您完全指定哪个函数/类可以在您自己的代码中创建/复制对象,并且不对库的代码进行任何假设 .