编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第11章_C++17特性.cpp -o t && ./t(需先 cd 测试/)
// 第11章测试:C++17 新特性
#include <print>
#include <optional>
#include <variant>
#include <any>
#include <string>
#include <string_view>
#include <map>
#include <vector>
#include <fstream>
#include <filesystem>
#include <numeric>
#include <type_traits>
namespace fs = std::filesystem;
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
std::optional<int> find_max(const std::vector<int>& v) {
if (v.empty()) return std::nullopt;
return *std::max_element(v.begin(), v.end());
}
[[nodiscard]] int must_use() { return 1; }
int main() {
// 11.1 结构化绑定
std::map<std::string, int> m{{"a", 1}, {"b", 2}};
int sum = 0;
for (auto [k, val] : m) sum += val;
CHECK(sum == 3);
auto [x, y] = std::pair{3, 4};
CHECK(x == 3 && y == 4);
auto [ta, tb, tc] = std::tuple{1, 2.5, std::string{"s"}};
CHECK(ta == 1 && tb == 2.5 && tc == "s");
// 11.2 if 初始化
auto it = m.find("b");
(void)it;
if (auto it2 = m.find("b"); it2 != m.end()) {
CHECK(it2->second == 2);
}
// it2 在这里已不可见(能编译通过即证明作用域正确)
// 11.3 optional
CHECK(find_max({3, 1, 4}) == 4);
CHECK(!find_max({}).has_value());
CHECK(find_max({}).value_or(-1) == -1);
// 11.4 variant
std::variant<int, double, std::string> v;
v = 42;
CHECK(std::get_if<int>(&v) != nullptr);
v = "text";
CHECK(std::get_if<std::string>(&v) != nullptr);
CHECK(std::get<std::string>(v) == "text");
// 错误类型访问会抛 bad_variant_access
bool threw = false;
try { std::get<int>(v); } catch (const std::bad_variant_access&) { threw = true; }
CHECK(threw);
// visit 统一访问(注意:lambda 要为每种类型都能编译,
// 这里用 if constexpr 区分类型——见第十章)
int visited = 0;
std::visit([&visited](const auto& val) {
if constexpr (std::is_same_v<std::decay_t<decltype(val)>, std::string>)
visited = (int)val.size();
}, v);
CHECK(visited == 4);
// 11.5 any
std::any a = 42;
a = std::string("hello");
CHECK(std::any_cast<std::string>(a) == "hello");
// 11.7 filesystem
fs::path test_dir = "/tmp/fs_test";
fs::remove_all(test_dir); // 清干净
fs::create_directories(test_dir / "sub" / "deep");
CHECK(fs::exists(test_dir));
CHECK(fs::is_directory(test_dir));
fs::path f = test_dir / "data.txt";
{
std::ofstream out(f);
out << "hello";
}
CHECK(fs::exists(f));
CHECK(fs::is_regular_file(f));
CHECK(fs::file_size(f) == 5);
CHECK(f.stem() == "data");
CHECK(f.extension() == ".txt");
// 目录遍历
int files = 0, dirs = 0;
for (const auto& entry : fs::recursive_directory_iterator(test_dir)) {
if (entry.is_regular_file()) ++files;
if (entry.is_directory()) ++dirs;
}
CHECK(files == 1);
CHECK(dirs == 2); // sub 和 sub/deep
fs::remove_all(test_dir);
CHECK(!fs::exists(test_dir));
// 11.11 nodiscard 属性(编译期验证:用法正确)
CHECK(must_use() == 1);
// 11.12 clamp / size
CHECK(std::clamp(10, 0, 5) == 5);
CHECK(std::clamp(-3, 0, 5) == 0);
int raw[4] = {1, 2, 3, 4};
CHECK(std::size(raw) == 4);
if (failures == 0) std::println("全部通过");
return failures;
}