1.通过 std::enable_if 实现条件模板实例化
std::enable_if 可以帮助你根据类型特征启用或禁用特定的模板函数。它是C++中一种非常强大的SFINAE(Substitution Failure Is Not An Error)技巧,能够根据传入的类型条件选择函数重载。 示例:
#include
#include
template
typename std::enable_if::value>::type print(T value) {
std::cout << "Integral: " << value << std::endl;
}
template
typename std::enable_if::value>::type print(T value) {
std::cout << "Floating point: " << value << std::endl;
}
int main() {
print(42); // 输出 Integral: 42
print(3.14); // 输出 Floating point: 3.14
}
通过 2.std::move_iterator 优化容器间的转移操作
std::move_iterator 可以在遍历容器时避免不必要的拷贝,通过移动元素来提高效率。这在大量数据移动(而非拷贝)时非常有用。
#include
#include
#include
#include
int main() {
std::vector src = {"1", "2", "3", "4"};
std::vector dest;
dest.reserve(src.size());
std::move_iterator::iterator> begin(src.begin());
std::move_iterator::iterator> end(src.end());
std::copy(begin, end, std::back_inserter(dest));
for (auto& x : src) {
std::cout << x << " "; //
}
for (auto& x : dest) {
std::cout << x << " "; // 输出 1 2 3 4
}
}
使用 3.std::source_location 提供丰富的调试信息
C++20引入了 std::source_location,它允许在程序运行时获取代码的文件名、行号和函数名等信息。你可以用它来方便地调试,特别是在日志输出时提供详细的源代码信息。
#include
#include
void log(const std::string& message, const std::source_location location = std::source_location::current()) {
std::cout << "File: " << location.file_name()
<< ", Line: " << location.line()
<< ", Function: " << location.function_name() << "\n"
<< message << std::endl;
}
int main() {
log("An error occurred!");
}
通过 4.std::tuple 和 std::index_sequence 实现变参模板优化
std::tuple 和 std::index_sequence 允许你在模板中传递和操作多个参数。通过结合这些工具,可以实现变参模板的高效处理,特别是在需要逐一操作每个参数时。
#include
#include
#include
// 用来打印单个元组元素
template
void print_tuple(const Tuple& t, std::index_sequence) {
// 展开每个索引,调用 std::get(t) 获取元组的元素
(..., (std::cout << std::get(t) << " ")); // C++17 的折叠表达式
}
// 对外接口:隐藏了索引生成的逻辑
template
void print(Args&&... args) {
// 创建元组,自动生成索引序列,并调用 print_tuple
print_tuple(std::make_tuple(std::forward(args)...),
std::index_sequence_for{});
}
int main() {
print(1, 2.5, "Hello", 'C'); // 输出:1 2.5 Hello C
return 0;
}
5.在模板元编程中使用if constexpr进行编译时switch
#include
#include
template
void printType(T value) {
if constexpr (std::is_integral_v) {
std::cout << "Integer: " << value << '\n';
} else if constexpr (std::is_floating_point_v) {
std::cout << "Float: " << value << '\n';
} else {
std::cout << "Other: " << value << '\n';
}
}
int main() {
printType(42); // Integer
printType(3.14); // Float
printType("C++!"); // Other
}
6.SFINAE:检测类是否有某成员函数
通过 SFINAE(Substitution Failure Is Not An Error)机制,可以检测某个类是否有特定的成员函数。
#include
#include
template
class HasToString {
private:
template
static auto test(int) -> decltype(std::declval().toString(), std::true_type{});
template
static std::false_type test(...);
public:
static constexpr bool value = decltype(test(0))::value;
};
struct A {
void toString() {}
};
struct B {};
int main() {
std::cout << "A has toString: " << HasToString::value << "\n"; // true
std::cout << "B has toString: " << HasToString::value << "\n"; // false
return 0;
}
7.RAII:std::shared_ptr 自定义析构函数
可以利用 std::shared_ptr 的自定义析构函数,管理复杂资源,比如文件句柄、锁等。
#include
#include
#include
struct FileDeleter {
void operator()(FILE* file) const {
if (file) {
std::cout << "Closing file\n";
fclose(file);
}
}
};
int main() {
std::shared_ptr file(fopen("example.txt", "w"), FileDeleter{});
if (file) {
fputs("Hello, World!", file.get());
}
return 0;
}
8.编译期计算:constexpr 求解递归问题
使用 constexpr 编写可以在编译期执行的递归算法。
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int result = factorial(5);
std::cout << "Factorial of 5: " << result << "\n";
return 0;
}
9.隐藏模板参数中的数据
通过类型参数“隐藏”编译期数据。
#include
template
struct HiddenData {
static constexpr int value = N;
};
template
void reveal() {
std::cout << "Hidden value: " << T::value << "\n";
}
int main() {
reveal>(); // 输出:Hidden value: 42
return 0;
}
10. 编译期字符串计算
通过模板元编程,在编译期计算字符串的长度或其他属性。
#include
#include
template
constexpr std::size_t constexpr_strlen(const char (&str)[N]) {
return N - 1; // 去掉 '\0'
}
int main() {
constexpr auto len = constexpr_strlen("Hello, World!");
static_assert(len == 13, "Length mismatch");
std::cout << "Length: " << len << "\n";
return 0;
}
总结
C++ 是一门充满深度和挑战的语言,它不仅提供了强大的功能,还蕴藏着许多鲜为人知的“黑科技”和奇淫技巧。通过对这些技巧的掌握,比如模板元编程、递归 Lambda、编译期计算、类型擦除等,开发者可以更高效地解决复杂问题,优化代码性能,并探索语言的无限可能。然而,这些技巧也往往伴随着复杂性和维护难度,因此在实际应用中需要慎重权衡。学会这些“神技”,不仅能让你在编程中游刃有余,更能开拓思维,成为真正的 C++ 大师!