下面的代码在Visual Studio的Visual C++ 19.0编译器上编译得很好,但gcc 5.4.0抱怨复制构造函数是私有的。
#include <map>
class CMyClass
{
public:
CMyClass(int) {};
private:
CMyClass(const CMyClass&); // I want to avoid copy construction
};
int main()
{
std::map<int, CMyClass> mymap;
mymap.emplace(0, 0);
return 0;
}
错误信息:
‘CMyClass::CMyClass(const CMyClass&)’ is private
避免复制不正是emplace
的目的吗?我错过了什么吗?
发布的 C++11 中无效。
C++11 标准描述了两个具有两个参数的pair
构造函数:
pair(const T1& x, const T2& y);
template<class U, class V> pair(U&& x, V&& y);
如果第一个被选中,你注定要失败,原因很明显。
第二个重载不参与重载解析,如果,如这里相关,"V
不能隐式转换为second_type
"。在这里,V
是int
,second_type
是CMyClass
。int
可以隐式转换为CMyClass
吗?否,因为声明CMyClass x = some_int;
格式不正确,如 C++11 中,声明名义上从 some_int
构造一个临时CMyClass
,然后将其移动到 x 中,但CMyClass
不能移动。
添加的额外重载 GCC - 允许 - 具有类似的约束。
C++17 大幅修改了对 pair
构造函数的约束,这具有允许代码工作的副作用。实现者将其视为追溯缺陷修复,这就是GCC 6接受您的代码的原因。
GCC 5.4.0 仅在启用相关重载时检查类型是否可转换:
// DR 811.
template<class _U1, class = typename
enable_if<is_convertible<_U1, _T1>::value>::type>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
而较新版本的 GCC 会检查它是否可移动可构造:
288 template<typename _U1, typename
289 enable_if<_PCCP::template
290 _MoveCopyPair<true, _U1, _T2>(),
291 bool>::type=true>
292 constexpr pair(_U1&& __x, const _T2& __y)
293 : first(std::forward<_U1>(__x)), second(__y) { }
特别是_PCCP
是_PCC<true, _T1, _T2>
的别名。 _PCC
是一个包含此函数的 traits 类:
138 template <bool __implicit, typename _U1, typename _U2>
139 static constexpr bool _MoveCopyPair()
140 {
141 using __do_converts = __and_<is_convertible<_U1&&, _T1>,
142 is_convertible<const _U2&, _T2>>;
143 using __converts = typename conditional<__implicit,
144 __do_converts,
145 __not_<__do_converts>>::type;
146 return __and_<is_constructible<_T1, _U1&&>,
147 is_constructible<_T2, const _U2&&>,
148 __converts
149 >::value;
150 }