เมตาโปรแกรมของฉันค้นหาโซลูชันทั้งหมด 92 รายการ พวกเขาจะพิมพ์เป็นข้อความผิดพลาด:
error: 'solution' is not a member of 'print<15863724>'
นี่หมายความว่าควรวางราชินีคนแรกที่ y = 1, ที่สองที่ y = 5, ที่สามที่ y = 8 เป็นต้นไป
ก่อนอื่นฟังก์ชันเมตาที่มีประโยชน์บางประการ:
template <typename T>
struct return_
{
typedef T type;
};
template <bool Condition, typename Then, typename Else>
struct if_then_else;
template <typename Then, typename Else>
struct if_then_else<true, Then, Else> : return_<Then> {};
template <typename Then, typename Else>
struct if_then_else<false, Then, Else> : return_<Else> {};
template <int N>
struct constant
{
enum { value = N };
};
template <int N>
struct print
{
// empty body -> member access yields a compiler error involving N
};
จากนั้นฟังก์ชันเมตาสองฟังก์ชันที่น่าสนใจ (สังเกตเอกพจน์และพหูพจน์):
template <int queens, int rows, int sums, int difs, int x, int y>
struct put_queen;
template <int queens, int rows, int sums, int difs, int x>
struct put_queens : constant
< put_queen<queens, rows, sums, difs, x, 1>::value
+ put_queen<queens, rows, sums, difs, x, 2>::value
+ put_queen<queens, rows, sums, difs, x, 3>::value
+ put_queen<queens, rows, sums, difs, x, 4>::value
+ put_queen<queens, rows, sums, difs, x, 5>::value
+ put_queen<queens, rows, sums, difs, x, 6>::value
+ put_queen<queens, rows, sums, difs, x, 7>::value
+ put_queen<queens, rows, sums, difs, x, 8>::value > {};
template <int queens, int rows, int sums, int difs, int x, int y>
struct put_queen : if_then_else<
rows & (1 << y) || sums & (1 << (x + y)) || difs & (1 << (8 + x - y)),
constant<0>,
put_queens<queens * 10 + y, rows | (1 << y), sums | (1 << (x + y)),
difs | (1 << (8 + x - y)), x + 1>
>::type {};
ตัวแปรจะqueens
เก็บพิกัด y ของราชินีที่วางไว้บนกระดาน ตัวแปรสามตัวต่อไปนี้จัดเก็บแถวและเส้นทแยงมุมที่ถูกครอบครองโดยราชินี
x
และy
ควรอธิบายด้วยตนเอง
อาร์กิวเมนต์แรกเพื่อif_then_else
ตรวจสอบว่าตำแหน่งปัจจุบันถูกบล็อก ถ้าเป็นเช่นนั้นการเรียกซ้ำจะหยุดลงโดยส่งกลับผลลัพธ์ (ไร้ความหมาย) 0 มิฉะนั้นราชินีจะถูกวางไว้บนกระดานและกระบวนการดำเนินการต่อด้วยคอลัมน์ถัดไป
เมื่อ x ถึง 8 เราพบวิธีแก้ไข:
template <int queens, int rows, int sums, int difs>
struct put_queens<queens, rows, sums, difs, 8>
{
enum { value = print<queens>::solution };
};
เนื่องจากprint
เทมเพลตไม่มีสมาชิกsolution
คอมไพเลอร์จะสร้างข้อผิดพลาด
และสุดท้ายเพื่อเริ่มกระบวนการเราตรวจสอบvalue
สมาชิกของกระดานว่าง:
int go = put_queens<0, 0, 0, 0, 0>::value;
โปรแกรมที่สมบูรณ์สามารถพบได้ที่ideone