为什么地图不包含 out_of_range?
Why does map not include out_of_range?
考虑以下无法编译的代码:
#include <map>
//#include <stdexcept> // uncommenting this works
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
为什么 std::map
不包含 std::out_of_range
,即使它使用它? (.at()
可以抛出一个 std::out_of_range
)。
当我还包含 <stdexcept>
时,它会编译,并且工作正常。
std::map
的实现不必全部在头文件中。是的,这是一个 class 模板,但可以免费使用任何内部非模板组件。
因此,头文件不必提及 std::out_of_range
(它很可能隐藏在那些非模板组件之一中)因此不必在任何地方都可见其定义,或者表现得好像它包含 <stdexcept>
。它是明确允许的,但标准中没有隐含或明确的义务要求它这样做。所以它可能会,也可能不会。
事实上 g++-9
的行为就好像 <map>
包含 <stdexcept>
,而 g++-10
不包含,并且在这两种情况下它们都是正确的。
标准 header 是否包含另一个 header 是一个实现细节,除非明确指定。
模板有点复杂,但只是为了给您指明方向,请考虑这个玩具示例:
// header: my_map.h
struct my_map {
int at(int);
};
仅在源文件中必须包含异常的 header:
// source: my_map.cpp
#include <stdexcept>
int my_map::at(int) {
throw std::out_of_range("bla");
}
std::map
肯定看起来不同,但它也可能隐藏 header 的异常。
Is it also ok for a header to not include a decl for std::pair
指定通过 <map>
包含的 header 是 <compare>
(C++20 起) 和 <initializer_list>
(C++11 起) .仅此而已。
<map>
可能包括其他 header,这是评论中提到的“实施细节”之一。明确允许标准 headers 包含其他标准的部分是 [todo.put 此处引用]。
避免此类头疼的简单经验法则是:包括您使用的内容。
but throwing std::out_of_range is not an "implementation detail" - it is part of the specification of std::map!
考虑到此代码使用 gcc 10.2:
编译
#include <map>
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(...) {
return 1;
}
return 0;
}
抛出并捕获out_of_range
异常,返回1。我们知道 at
可能会抛出什么,而 catch(...)
会捕获它,但异常不需要 include。
另一方面,同一个编译器rejects your example, but compiles it当我们添加一个看似无关的header:
#include <map>
#include <sstream> // why this?
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
然而,这只是巧合。显然 <sstream>
确实包括 <stdexcept>
沿线的某处。但这可能会随着编译器版本或不同编译器而改变。
Why does std::map not include std::out_of_range
假设您使用的是 GCC 10,GCC 开发人员决定优化 header C++ 标准库代码中的依赖项。来自 Porting to GCC 10:
Header dependency changes
Some C++ Standard Library headers have been changed to no longer
include the <stdexcept> header. As such, C++ programs that used
components defined in <stdexcept> or <string> without explicitly
including the right headers will no longer compile.
Previously components such as std::runtime_error, std::string and
std::allocator were implicitly defined after including unrelated
headers such as <array> and <optional>. Correct code should include
the appropriate headers for the classes being used.
Reduced header dependencies, leading to faster compilation for some
code.
考虑以下无法编译的代码:
#include <map>
//#include <stdexcept> // uncommenting this works
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
为什么 std::map
不包含 std::out_of_range
,即使它使用它? (.at()
可以抛出一个 std::out_of_range
)。
当我还包含 <stdexcept>
时,它会编译,并且工作正常。
std::map
的实现不必全部在头文件中。是的,这是一个 class 模板,但可以免费使用任何内部非模板组件。
因此,头文件不必提及 std::out_of_range
(它很可能隐藏在那些非模板组件之一中)因此不必在任何地方都可见其定义,或者表现得好像它包含 <stdexcept>
。它是明确允许的,但标准中没有隐含或明确的义务要求它这样做。所以它可能会,也可能不会。
事实上 g++-9
的行为就好像 <map>
包含 <stdexcept>
,而 g++-10
不包含,并且在这两种情况下它们都是正确的。
标准 header 是否包含另一个 header 是一个实现细节,除非明确指定。
模板有点复杂,但只是为了给您指明方向,请考虑这个玩具示例:
// header: my_map.h
struct my_map {
int at(int);
};
仅在源文件中必须包含异常的 header:
// source: my_map.cpp
#include <stdexcept>
int my_map::at(int) {
throw std::out_of_range("bla");
}
std::map
肯定看起来不同,但它也可能隐藏 header 的异常。
Is it also ok for a header to not include a decl for std::pair
指定通过 <map>
包含的 header 是 <compare>
(C++20 起) 和 <initializer_list>
(C++11 起) .仅此而已。
<map>
可能包括其他 header,这是评论中提到的“实施细节”之一。明确允许标准 headers 包含其他标准的部分是 [todo.put 此处引用]。
避免此类头疼的简单经验法则是:包括您使用的内容。
but throwing std::out_of_range is not an "implementation detail" - it is part of the specification of std::map!
考虑到此代码使用 gcc 10.2:
编译#include <map>
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(...) {
return 1;
}
return 0;
}
抛出并捕获out_of_range
异常,返回1。我们知道 at
可能会抛出什么,而 catch(...)
会捕获它,但异常不需要 include。
另一方面,同一个编译器rejects your example, but compiles it当我们添加一个看似无关的header:
#include <map>
#include <sstream> // why this?
int main() {
std::map<int, int> test;
try {
test.at(10);
} catch(std::out_of_range& e) {
}
return 0;
}
然而,这只是巧合。显然 <sstream>
确实包括 <stdexcept>
沿线的某处。但这可能会随着编译器版本或不同编译器而改变。
Why does std::map not include std::out_of_range
假设您使用的是 GCC 10,GCC 开发人员决定优化 header C++ 标准库代码中的依赖项。来自 Porting to GCC 10:
Header dependency changes
Some C++ Standard Library headers have been changed to no longer include the <stdexcept> header. As such, C++ programs that used components defined in <stdexcept> or <string> without explicitly including the right headers will no longer compile.
Previously components such as std::runtime_error, std::string and std::allocator were implicitly defined after including unrelated headers such as <array> and <optional>. Correct code should include the appropriate headers for the classes being used.
Reduced header dependencies, leading to faster compilation for some code.