下面非常简单的代码在C 98中编译和链接时没有警告,但在C 11模式下会出现无法理解的编译错误。
#include <map>
struct A {
A(A& ); // <-- const missing
};
int main() {
std::map<int, A> m;
return m.begin() == m.end(); // line 9
}
标准=c 11的错误是,gcc版本4.9.0 20140302(实验)(gcc):
ali@X230:~/tmp$ ~/gcc/install/bin/g++ -std=c++11 cctor.cpp In file included from /home/ali/gcc/install/include/c++/4.9.0/bits/stl_algobase.h:64:0, from /home/ali/gcc/install/include/c++/4.9.0/bits/stl_tree.h:61, from /home/ali/gcc/install/include/c++/4.9.0/map:60, from cctor.cpp:1: /home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h: In instantiation of ‘struct std::pair’: cctor.cpp:9:31: required from here /home/ali/gcc/install/include/c++/4.9.0/bits/stl_pair.h:127:17: error: ‘constexpr std::pair::pair(const std::pair&) [with _T1 = const int; _T2 = A]’ declared to take const reference, but implicit declaration would take non-const constexpr pair(const pair&) = default; ^
带clang版本3.5(trunk 202594)
ali@X230:~/tmp$ clang++ -Weverything -std=c++11 cctor.cpp In file included from cctor.cpp:1: In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/map:60: In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_tree.h:63: In file included from /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_algobase.h:65: /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/stl_pair.h:119:17: error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be non-const constexpr pair(const pair&) = default; ^ cctor.cpp:9:22: note: in instantiation of template class 'std::pair' requested here return m.begin() == m.end(); // line 9 ^ 1 error generated.
我一直在看bit/stl_tree. h
中的代码,我不明白为什么它试图实例化std::对
。
为什么在C 11中需要复制构造函数std::pair?
注:上述代码是从不可复制映射的映射迭代器上不支持的等式运算符(=)中提取的
解决方案
这里有两个不幸的问题。
质量差的错误消息:第8行应该已经给出了编译错误,尽管错误消息只是抱怨第9行。在第8行中得到一个错误将非常有帮助,了解真正的问题将更加容易。如果gcc/clang trunk中仍然存在此问题,我可能会提交错误报告/功能请求。
另一个问题是ecatmur写什么。考虑以下代码:
struct A {
A() = default;
A(A& ); // <-- const missing
};
template<class T>
struct B {
B() = default;
B(const B& ) = default;
T t;
};
int main() {
B<A> b;
}
它无法编译。即使任何地方都不需要复制构造函数,但它仍然被实例化,因为它是默认内联的,在类的主体中;这会导致编译错误。这可以通过将复制构造函数移出类的主体来修复:
template<class T>
struct B {
B() = default;
B(const B& );
T t;
};
template <class T>
B<T>::B(const B& ) = default;
那么一切都好了。不幸的是,std::pair有一个默认定义的内联复制构造函数。
我想我是在试图减少错误后发现的。首先,似乎不需要进行比较就可以使程序格式错误。然后,错误消息包含dtor,因此我尝试不实例化dtor。结果:
#include <map>
struct A {
A(A& ); // <-- const missing
};
int main() {
std::map<int, A>* m = new std::map<int, A>();
// note: dtor not (necessarily?) instantiated
}
但是输出消息仍然包含,现在对于调用m的ctor的行:
错误:此显式默认复制构造函数的参数为常量,但成员或基要求它为非常量
constexpr pair(const pair&) = default;
[dcl.fct.def.def.default]的提示/4
用户提供的显式默认函数(即在其第一次声明后显式默认)在显式默认点定义;如果这样的函数被隐式定义为已删除,则程序格式错误。
[强调地雷]
如果像我假设的那样,[class.copy]/11说应该将这个ctor定义为deleted,那么它将被定义为立即删除,而不仅仅是在使用odr时。因此,不需要实例化来使程序格式错误。
std::map
使用std::pair
存储键值对,其中键(第一个元素)是常量。
编译器错误与std::pair所需的复制构造函数有关,即使它没有被使用(我认为不是)。
<代码>标准::对
隐式构造函数将具有签名T::T(const T
A的复制构造函数没有满足此要求,因此std::pair::pair对STL的签名错误,这需要T::T(const T
在这种情况下,不需要std::pair的copy构造函数,但由于它是在std::pair的声明中内联定义的默认构造函数,因此它会与std::pair本身的实例化一起自动实例化。
标准库可以提供复制构造函数的非内联默认定义:
template<class _T1, class _T2>
struct pair
{
// ...
constexpr pair(const pair&);
// ...
};
// ...
template<class _T1, class _T2>
constexpr pair<_T1, _T2>::pair(const pair&) = default;
但是,这不符合标准的严格要求(第20.3.2条),其中复制构造函数是默认的内联定义:
constexpr pair(const pair&) = default;
考虑一个大型内存容器。在这个简单的例子中 span允许我在内存上创建一个轻量级视图。现在,我只想打印跨度: 输出: 现在我想制作子集(这是实际上作为视图变得有用的地方)。我可以使用迭代器来指定我的范围并从调用这个构造函数(3) 但这行不通: C没有与参数列表匹配的构造函数实例参数类型为:(std::\u Vector\u iterator 有可能使用接受指针和大小的构造函数(2): 但这违背了迭代
我想知道为什么c标准要求只接受随机访问迭代器?我不认为这有什么好处,因为std::sort和std::list::sort的复杂性都是。将限制为随机访问迭代器(RAI),似乎需要为具有相同复杂性的列表编写单独的函数。 同样的情况也适用于,其中列表的非RAI计数器部分至今仍然缺失。 这种设计是因为历史上人们使用了的变体来实现? 如果在RAI容器上编写排序算法有好处,那么最好使更通用,并让像这样的RA
我想知道为什么std::map和std::set使用std::less作为比较键的默认函子。为什么不使用一个类似strcmp的函子呢?类似于: 假设地图中有两个对象,分别是键1和键2。现在,我们要插入另一个具有键3的对象。 如果使用,那么只需一个调用就有足够的信息来做出正确的决定。 根据映射中键的类型,可能很昂贵。 除非我缺少一些非常基本的东西,否则不应该使用类似于比较的东西,而不是作为比较键的默
问题内容: 必须使用无参数构造函数(像Hibernate这样的工具会在此构造函数上使用反射来实例化对象)。 我得到了这个手挥手的答案,但是有人可以进一步解释吗?谢谢 问题答案: hibernate,并且通常通过反射创建对象的代码用于创建类的新实例。此方法需要一个公共的无参数构造函数才能实例化该对象。对于大多数用例,提供无参数构造函数不是问题。 有一些基于序列化的技巧可以解决没有no-arg构造函数
问题内容: 这对您来说可能听起来很愚蠢,但是为什么我需要在s中定义一个空的构造函数? 我看到的每个教程都说:每个实体都需要一个空的构造函数。 但是Java总是给您一个默认的不可见的空构造函数(如果您不重新定义一个的话)。 谢谢。 我认为这是一个语义问题。我所理解的“需求”是书面的。 含义:始终在您的实体中编写一个空的构造函数。 例: 但是,当您不重新定义Java时,Java总是会为您提供一个空的构
问题内容: 我对此代码有疑问:https : //github.com/reactjs/redux/blob/master/examples/async/containers/App.js 特别: 我猜这是一个两部分的问题。 为什么我需要将句柄更改设置为类的实例,我不能只对handleChange使用静态函数并直接在类中调用它 ? 我不知道这是怎么回事: 谢谢 问题答案: 以相反的顺序回答… 返回