Cố gắng chuyên môn hóa dựa trên tính hợp lệ của kích thước mảng:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return 0; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
// negative case template
template<int p>
struct absolute<p, typename std::void_t<int[-p]>> {
operator int () const { return -p; }
};
int main() {
std::cout << absolute<5>() << std::endl;
std::cout << absolute<-5>() << std::endl;
std::cout << absolute<0>() << std::endl;
}
Vấn đề # 1:
Mã trên hoạt động độc đáo với gcc nhưng không biên dịch với tiếng kêu .
Clang tạo ra lỗi: xác định lại cấu trúc mẫu 'tuyệt đối'
Ai đúng?
Vấn đề 2:
Cả với gcc và với tiếng kêu (nếu chúng tôi loại bỏ chuyên môn tiêu cực để đưa tiếng kêu trở lại trò chơi), không rõ lý do tại sao absolute<0>()
chọn mẫu cơ sở. Không có gì sai với int[0]
cũng như std::void_t<int[0]>
dường như chuyên sâu hơn:
// base template
template<int p, typename T = void>
struct absolute {
operator int () const { return -1; }
};
// positive case template
template<int p>
struct absolute<p, typename std::void_t<int[p]>> {
operator int () const { return p; }
};
int main() {
std::cout << absolute<5>() << std::endl; // 5
std::cout << absolute<0>() << std::endl; // -1, why not 0?
}
Và ... nếu mẫu cơ sở chỉ được khai báo mà không thực hiện, như:
// base template
template<int p, typename T = void>
struct absolute;
Cả gcc và clang đều không thể biên dịch , phàn nàn về việc sử dụng loại không đầy đủ cho cuộc gọi : absolute<0>()
. Mặc dù nó có vẻ phù hợp với trường hợp chuyên ngành.
Tại sao vậy?
int[0]
Cấm bởi các tiêu chuẩn ISO C ++ chuẩn timsong-cpp.github.io/cppwp/n4659/dcl.array#1 "giá trị của nó sẽ lớn hơn không"
template<int p> struct absolute<p, typename std::void_t<int[p]>>
vàtemplate<int p> struct absolute
đó không phải là một bản sao?