1. Vấn đề nó giải quyết
Non-type template parameter trước đây yêu cầu ghi type cụ thể dù value đã làm type rõ. C++17 cho phép auto để một template nhận nhiều constant-value type được hỗ trợ.
2. Kiến thức cần có
Compiler hỗ trợ C++17, được gọi với warning đầy đủ, cùng các bài trước theo thứ tự của khóa học.
Biết type template parameter, compile-time constant,
decltypevà integral constant expression.
3. Ý tưởng cốt lõi
Trong template<auto Value>, deduction xác định cả value lẫn type khi instantiate. Value vẫn là compile-time template argument; value hoặc type khác tạo specialization khác.
4. Cú pháp tối thiểu
template<auto Value>
struct Constant {
static constexpr auto value = Value;
};5. Cách nó hoạt động
Cùng class template được instantiate một lần với integer và một lần với character.
decltype(Value)được suy ra riêng cho từng specialization, còn inline constexpr storage cung cấp constant không cần runtime state.Chương trình in
integer: 42vàcharacter: Z, tạo test oracle nhỏ để so sánh với dự đoán trước khi biên dịch.
6. Lỗi thường gặp
Argument phải là non-type value compile time được phép; runtime object tùy ý và nhiều value phụ thuộc address không dùng được.
Build thành công chưa đủ; phải kiểm tra lifetime, ordering và error path.
7. Khi nào nên dùng
Nên dùng kỹ thuật này khi behavior hoặc storage phụ thuộc compile-time value có exact type được hỗ trợ có thể thay đổi.
Nên chọn cách C++11/14 đơn giản hơn nếu quy tắc C++17 không cải thiện safety, độ rõ hoặc hiệu năng đã đo trên các toolchain phải hỗ trợ.
8. Ví dụ đơn giản
Static assertion xác nhận integer và character giữ type của chúng. Runtime printing chỉ làm các lựa chọn compile time nhìn thấy được.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp17/15_auto_non_type_template_parameters/main.cpp
#include <iostream>
#include <type_traits>
template <auto Value>
struct Constant {
inline static constexpr auto value = Value;
};
int main() {
static_assert(std::is_same_v<
decltype(Constant<42>::value), const int>);
static_assert(std::is_same_v<
decltype(Constant<'Z'>::value), const char>);
std::cout << "integer: " << Constant<42>::value << '\n';
std::cout << "character: " << Constant<'Z'>::value << '\n';
}
9. Điều cần nhớ
autolàm non-type template tổng quát hơn nhưng không biến runtime value thành template argument.Phải chọn rõ chế độ C++17; default của compiler mới hơn có thể che lỗi portability.
Warning và ví dụ xác định biến quy tắc ghi nhớ thành bằng chứng.
10. Câu hỏi tự kiểm tra
Dễ — Non-type template parameters với auto giải quyết vấn đề chính nào?
Trung bình — Type nào được suy ra cho
Constant<'Z'>::value?Khó — Vì sao
Constant<1>vàConstant<1L>là hai specialization khác nhau?