Memecahkan masalah delapan ratu pada waktu kompilasi [ditutup]

39

Bisakah Anda memecahkan teka-teki delapan ratu pada waktu kompilasi?

Pilih format output yang cocok.

Saya sangat tertarik dengan solusi metaprogramming template C ++, tetapi Anda dapat menggunakan bahasa yang memiliki konstruksi serupa, seperti, misalnya, sistem tipe Haskell.

Idealnya metaprogram Anda akan menampilkan semua solusi. Tidak ada hardcoding.

R. Martinho Fernandes
sumber
Mengapa Anda tidak mengizinkan bahasa yang berbeda?
pengguna tidak diketahui
@ pengguna: Karena saya tertarik dengan solusi C ++ TMP. Jika Anda tahu bahasa yang memiliki konstruksi sangat mirip, jangan ragu untuk mengirim jawaban.
R. Martinho Fernandes
Bisakah saya juga menggunakan sistem tipe Haskell? AFAIK itu harus turing lengkap.
FUZxxl
@ FuZxxl: Ya. Saya akan mengedit pertanyaan.
R. Martinho Fernandes
Apakah cukup untuk melakukan solusi brute force?
Berhenti menghidupkan counterclock dengan

Jawaban:

50

Program-meta saya menemukan semua 92 solusi. Mereka dicetak sebagai pesan kesalahan:

error: 'solution' is not a member of 'print<15863724>'

Ini berarti ratu pertama harus ditempatkan pada y = 1, yang kedua di y = 5, yang ketiga di y = 8 dan seterusnya.

Pertama, beberapa fungsi meta yang berguna:

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
};

Kemudian, dua fungsi meta yang menarik (perhatikan bentuk tunggal dan jamak):

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 {};

Variabel queensmenyimpan koordinat y dari ratu yang ditempatkan di papan sejauh ini. Tiga variabel berikut menyimpan baris dan diagonal yang sudah ditempati oleh ratu. xdan yharus jelas.

Argumen pertama untuk if_then_elsememeriksa apakah posisi saat ini diblokir. Jika ya, rekursi berhenti dengan mengembalikan hasil (yang tidak berarti) 0. Jika tidak, ratu ditempatkan di papan tulis, dan proses berlanjut dengan kolom berikutnya.

Ketika x mencapai 8, kami telah menemukan solusi:

template <int queens, int rows, int sums, int difs>
struct put_queens<queens, rows, sums, difs, 8>
{
    enum { value = print<queens>::solution };
};

Karena printtemplat tidak memiliki anggota solution, kompiler menghasilkan kesalahan.

Dan akhirnya, untuk memulai proses, kami memeriksa valueanggota dewan yang kosong:

int go = put_queens<0, 0, 0, 0, 0>::value;

Program lengkap dapat ditemukan di ideone .

fredoverflow
sumber
2
Saya suka: 1) menggunakan bitfields untuk menyimpan data, 2) pilihan metode output.
R. Martinho Fernandes
7
Terlalu banyak kemegahan untuk satu jawaban.
st0le
Tidakkah seharusnya juga menghasilkan nilai x?
DeadMG
2
@DeadMG Nilai x dari setiap lokasi ratu adalah posisinya dalam string (1-8).
Briguy37
22

Saya datang dengan solusi yang menggunakan sistem tipe Haskell. Saya mencari sedikit Google untuk solusi yang ada untuk masalah di tingkat nilai , mengubahnya sedikit, dan kemudian mengangkatnya ke tingkat tipe. Butuh banyak penemuan kembali. Saya juga harus mengaktifkan banyak ekstensi GHC.

Pertama, karena bilangan bulat tidak diperbolehkan pada level tipe, saya perlu menemukan kembali bilangan alami sekali lagi, kali ini sebagai tipe:

data Zero -- type that represents zero
data S n  -- type constructor that constructs the successor of another natural number
-- Some numbers shortcuts
type One = S Zero
type Two = S One
type Three = S Two
type Four = S Three
type Five = S Four
type Six = S Five
type Seven = S Six
type Eight = S Seven

Algoritma yang saya adaptasikan membuat penambahan dan pengurangan pada naturals, jadi saya harus menemukan kembali ini juga. Fungsi pada level tipe didefinisikan dengan kelas resort to type. Ini membutuhkan ekstensi untuk beberapa kelas tipe parameter dan dependensi fungsional. Tipe kelas tidak dapat "mengembalikan nilai", jadi kami menggunakan parameter tambahan untuk itu, dengan cara yang mirip dengan PROLOG.

class Add a b r | a b -> r -- last param is the result
instance Add Zero b b                     -- 0 + b = b
instance (Add a b r) => Add (S a) b (S r) -- S(a) + b = S(a + b)

class Sub a b r | a b -> r
instance Sub a Zero a                     -- a - 0 = a
instance (Sub a b r) => Sub (S a) (S b) r -- S(a) - S(b) = a - b

Rekursi diimplementasikan dengan pernyataan kelas, sehingga sintaks terlihat agak terbelakang.

Selanjutnya adalah boolean:

data True  -- type that represents truth
data False -- type that represents falsehood

Dan fungsi untuk melakukan perbandingan ketidaksetaraan:

class NotEq a b r | a b -> r
instance NotEq Zero Zero False                -- 0 /= 0 = False
instance NotEq (S a) Zero True                -- S(a) /= 0 = True
instance NotEq Zero (S a) True                -- 0 /= S(a) = True
instance (NotEq a b r) => NotEq (S a) (S b) r -- S(a) /= S(b) = a /= b

Dan daftar ...

data Nil
data h ::: t
infixr 0 :::

class Append xs ys r | xs ys -> r
instance Append Nil ys ys                                       -- [] ++ _ = []
instance (Append xs ys rec) => Append (x ::: xs) ys (x ::: rec) -- (x:xs) ++ ys = x:(xs ++ ys)

class Concat xs r | xs -> r
instance Concat Nil Nil                                         -- concat [] = []
instance (Concat xs rec, Append x rec r) => Concat (x ::: xs) r -- concat (x:xs) = x ++ concat xs

class And l r | l -> r
instance And Nil True                    -- and [] = True
instance And (False ::: t) False         -- and (False:_) = False
instance (And t r) => And (True ::: t) r -- and (True:t) = and t

ifs juga hilang pada tingkat tipe ...

class Cond c t e r | c t e -> r
instance Cond True t e t  -- cond True t _ = t
instance Cond False t e e -- cond False _ e = e

Dan dengan itu, semua mesin pendukung yang saya gunakan ada di tempatnya. Saatnya mengatasi masalah itu sendiri!

Dimulai dengan fungsi untuk menguji apakah menambahkan ratu ke papan yang ada sudah ok:

-- Testing if it's safe to add a queen
class Safe x b n r | x b n -> r
instance Safe x Nil n True    -- safe x [] n = True
instance (Safe x y (S n) rec,
          Add c n cpn, Sub c n cmn,
          NotEq x c c1, NotEq x cpn c2, NotEq x cmn c3,
          And (c1 ::: c2 ::: c3 ::: rec ::: Nil) r) => Safe x (c ::: y) n r
    -- safe x (c:y) n = and [ x /= c , x /= c + n , x /= c - n , safe x y (n+1)]

Perhatikan penggunaan asersi kelas untuk mendapatkan hasil antara. Karena nilai pengembalian sebenarnya merupakan parameter tambahan, kami tidak bisa langsung memanggil pernyataan satu sama lain secara langsung. Sekali lagi, jika Anda telah menggunakan PROLOG sebelum Anda mungkin menemukan gaya ini agak akrab.

Setelah saya membuat beberapa perubahan untuk menghilangkan kebutuhan lambda (yang bisa saya terapkan, tetapi saya memutuskan untuk pergi untuk hari lain), inilah yang tampak seperti solusi aslinya:

queens 0 = [[]]
-- The original used the list monad. I "unrolled" bind into concat & map.
queens n = concat $ map f $ queens (n-1)
g y x = if safe x y 1 then [x:y] else []
f y = concat $ map (g y) [1..8]

mapadalah fungsi urutan yang lebih tinggi. Saya pikir menerapkan meta-fungsi tingkat tinggi akan terlalu merepotkan (sekali lagi lambda) jadi saya hanya pergi dengan solusi yang lebih sederhana: karena saya tahu fungsi apa yang akan dipetakan, saya dapat mengimplementasikan versi khusus mapuntuk masing-masing, sehingga tidak fungsi tingkat tinggi.

-- Auxiliary meta-functions
class G y x r | y x -> r
instance (Safe x y One s, Cond s ((x ::: y) ::: Nil) Nil r) => G y x r

class MapG y l r | y l -> r
instance MapG y Nil Nil
instance (MapG y xs rec, G y x g) => MapG y (x ::: xs) (g ::: rec)

-- Shortcut for [1..8]
type OneToEight = One ::: Two ::: Three ::: Four ::: Five ::: Six ::: Seven ::: Eight ::: Nil

class F y r | y -> r
instance (MapG y OneToEight m, Concat m r) => F y r -- f y = concat $ map (g y) [1..8]

class MapF l r | l -> r
instance MapF Nil Nil
instance (MapF xs rec, F x f) => MapF (x ::: xs) (f ::: rec)

Dan meta-fungsi terakhir dapat ditulis sekarang:

class Queens n r | n -> r
instance Queens Zero (Nil ::: Nil)
instance (Queens n rec, MapF rec m, Concat m r) => Queens (S n) r

Yang tersisa hanyalah beberapa jenis driver untuk membujuk mesin pengecekan tipe untuk mencari solusinya.

-- dummy value of type Eight
eight = undefined :: Eight
-- dummy function that asserts the Queens class
queens :: Queens n r => n -> r
queens = const undefined

Program-meta ini seharusnya dijalankan pada pemeriksa tipe, sehingga orang dapat menjalankan ghcidan menanyakan jenis queens eight:

> :t queens eight

Ini akan melebihi batas rekursi default agak cepat (ini sangat sedikit 20). Untuk meningkatkan batas ini, kita perlu memanggil ghcidengan -fcontext-stack=Npilihan, di mana Nadalah kedalaman tumpukan yang diinginkan (N = 1000 dan lima belas menit tidak cukup). Saya belum melihat ini berjalan sampai selesai, karena itu membutuhkan waktu yang sangat lama, tetapi saya sudah berhasil berlari hingga queens four.

Ada program lengkap tentang ideone dengan beberapa mesin untuk mencetak tipe hasil yang cantik, tetapi hanya ada yang queens twobisa berjalan tanpa melebihi batas :(

R. Martinho Fernandes
sumber
Selain solusi yang menarik, ini adalah referensi yang menyenangkan untuk apa yang dapat dilakukan dengan logika kelas / instance
Michael Klein
11

C, melalui preprocessor

Saya pikir komite ANSI membuat pilihan sadar untuk tidak memperpanjang C preprocessor ke titik Turing-lengkap. Bagaimanapun, itu tidak cukup kuat untuk menyelesaikan masalah delapan ratu. Tidak dengan cara umum.

Tapi itu bisa dilakukan, jika Anda mau melakukan hard-code pada counter loop. Tidak ada cara nyata untuk mengulang, tentu saja, tetapi Anda dapat menggunakan inklusi diri (via #include __FILE__) untuk mendapatkan jenis rekursi terbatas.

#ifdef i
# if (r_(i) & 1 << j_(i)) == 0 && (p_(i) & 1 << i + j_(i)) == 0 \
                               && (n_(i) & 1 << 7 + i - j_(i)) == 0
#  if i == 0
#   undef i
#   define i 1
#   undef r1
#   undef p1
#   undef n1
#   define r1 (r0 | (1 << j0))
#   define p1 (p0 | (1 << j0))
#   define n1 (n0 | (1 << 7 - j0))
#   undef j1
#   define j1 0
#   include __FILE__
#   undef j1
#   define j1 1
#   include __FILE__
#   undef j1
#   define j1 2
#   include __FILE__
#   undef j1
#   define j1 3
#   include __FILE__
#   undef j1
#   define j1 4
#   include __FILE__
#   undef j1
#   define j1 5
#   include __FILE__
#   undef j1
#   define j1 6
#   include __FILE__
#   undef j1
#   define j1 7
#   include __FILE__
#   undef i
#   define i 0
#  elif i == 1
#   undef i
#   define i 2
#   undef r2
#   undef p2
#   undef n2
#   define r2 (r1 | (1 << j1))
#   define p2 (p1 | (1 << 1 + j1))
#   define n2 (n1 | (1 << 8 - j1))
#   undef j2
#   define j2 0
#   include __FILE__
#   undef j2
#   define j2 1
#   include __FILE__
#   undef j2
#   define j2 2
#   include __FILE__
#   undef j2
#   define j2 3
#   include __FILE__
#   undef j2
#   define j2 4
#   include __FILE__
#   undef j2
#   define j2 5
#   include __FILE__
#   undef j2
#   define j2 6
#   include __FILE__
#   undef j2
#   define j2 7
#   include __FILE__
#   undef i
#   define i 1
#  elif i == 2
#   undef i
#   define i 3
#   undef r3
#   undef p3
#   undef n3
#   define r3 (r2 | (1 << j2))
#   define p3 (p2 | (1 << 2 + j2))
#   define n3 (n2 | (1 << 9 - j2))
#   undef j3
#   define j3 0
#   include __FILE__
#   undef j3
#   define j3 1
#   include __FILE__
#   undef j3
#   define j3 2
#   include __FILE__
#   undef j3
#   define j3 3
#   include __FILE__
#   undef j3
#   define j3 4
#   include __FILE__
#   undef j3
#   define j3 5
#   include __FILE__
#   undef j3
#   define j3 6
#   include __FILE__
#   undef j3
#   define j3 7
#   include __FILE__
#   undef i
#   define i 2
#  elif i == 3
#   undef i
#   define i 4
#   undef r4
#   undef p4
#   undef n4
#   define r4 (r3 | (1 << j3))
#   define p4 (p3 | (1 << 3 + j3))
#   define n4 (n3 | (1 << 10 - j3))
#   undef j4
#   define j4 0
#   include __FILE__
#   undef j4
#   define j4 1
#   include __FILE__
#   undef j4
#   define j4 2
#   include __FILE__
#   undef j4
#   define j4 3
#   include __FILE__
#   undef j4
#   define j4 4
#   include __FILE__
#   undef j4
#   define j4 5
#   include __FILE__
#   undef j4
#   define j4 6
#   include __FILE__
#   undef j4
#   define j4 7
#   include __FILE__
#   undef i
#   define i 3
#  elif i == 4
#   undef i
#   define i 5
#   undef r5
#   undef p5
#   undef n5
#   define r5 (r4 | (1 << j4))
#   define p5 (p4 | (1 << 4 + j4))
#   define n5 (n4 | (1 << 11 - j4))
#   undef j5
#   define j5 0
#   include __FILE__
#   undef j5
#   define j5 1
#   include __FILE__
#   undef j5
#   define j5 2
#   include __FILE__
#   undef j5
#   define j5 3
#   include __FILE__
#   undef j5
#   define j5 4
#   include __FILE__
#   undef j5
#   define j5 5
#   include __FILE__
#   undef j5
#   define j5 6
#   include __FILE__
#   undef j5
#   define j5 7
#   include __FILE__
#   undef i
#   define i 4
#  elif i == 5
#   undef i
#   define i 6
#   undef r6
#   undef p6
#   undef n6
#   define r6 (r5 | (1 << j5))
#   define p6 (p5 | (1 << 5 + j5))
#   define n6 (n5 | (1 << 12 - j5))
#   undef j6
#   define j6 0
#   include __FILE__
#   undef j6
#   define j6 1
#   include __FILE__
#   undef j6
#   define j6 2
#   include __FILE__
#   undef j6
#   define j6 3
#   include __FILE__
#   undef j6
#   define j6 4
#   include __FILE__
#   undef j6
#   define j6 5
#   include __FILE__
#   undef j6
#   define j6 6
#   include __FILE__
#   undef j6
#   define j6 7
#   include __FILE__
#   undef i
#   define i 5
#  elif i == 6
#   undef i
#   define i 7
#   undef r7
#   undef p7
#   undef n7
#   define r7 (r6 | (1 << j6))
#   define p7 (p6 | (1 << 6 + j6))
#   define n7 (n6 | (1 << 13 - j6))
#   undef j7
#   define j7 0
#   include __FILE__
#   undef j7
#   define j7 1
#   include __FILE__
#   undef j7
#   define j7 2
#   include __FILE__
#   undef j7
#   define j7 3
#   include __FILE__
#   undef j7
#   define j7 4
#   include __FILE__
#   undef j7
#   define j7 5
#   include __FILE__
#   undef j7
#   define j7 6
#   include __FILE__
#   undef j7
#   define j7 7
#   include __FILE__
#   undef i
#   define i 6
#  elif i == 7
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           j0 + 1, j1 + 1, j2 + 1, j3 + 1, j4 + 1, j5 + 1, j6 + 1, j7 + 1);
#  endif
# endif
#else
#include <stdio.h>
#define _cat(a, b) a ## b
#define j_(i) _cat(j, i)
#define n_(i) _cat(n, i)
#define p_(i) _cat(p, i)
#define r_(i) _cat(r, i)
int main(void)
{
# define i 0
# define j0 0
# include __FILE__
# undef j0
# define j0 1
# include __FILE__
# undef j0
# define j0 2
# include __FILE__
# undef j0
# define j0 3
# include __FILE__
# undef j0
# define j0 4
# include __FILE__
# undef j0
# define j0 5
# include __FILE__
# undef j0
# define j0 6
# include __FILE__
# undef j0
# define j0 7
# include __FILE__
# undef j0
    return 0;
}
#endif

Terlepas dari jumlah konten berulang yang mengerikan, izinkan saya meyakinkan Anda bahwa itu benar-benar menyelesaikan masalah delapan ratu secara algoritmik. Sayangnya satu hal yang saya tidak bisa lakukan dengan preprocessor adalah menerapkan struktur data stack push-down umum. Hasilnya adalah bahwa saya harus meng-hard-code nilai di imana pun ia digunakan untuk memilih nilai lain untuk ditetapkan. (Berbeda dengan mengambil nilai, yang bisa dilakukan sepenuhnya secara umum. Itu sebabnya #ifdi bagian atas file, yang memutuskan apakah seorang ratu dapat ditambahkan pada posisi saat ini, tidak perlu diulang delapan kali.)

Dalam kode preprocessor, idan jmenunjukkan posisi saat ini sedang dipertimbangkan, sementara r, pdan nkeep track yang pangkat dan diagonal saat ini tidak tersedia untuk penempatan. Namun, ijuga berfungsi sebagai penghitung yang menandai kedalaman rekursi saat ini, sehingga benar-benar semua nilai lain benar-benar menggunakan i sebagai semacam subskrip, sehingga nilainya dipertahankan saat melanjutkan dari rekursi. (Dan juga karena kesulitan serius dalam memodifikasi nilai simbol preprosesor tanpa sepenuhnya menggantinya.)

Program yang dikompilasi mencetak semua 92 solusi. Solusi tertanam langsung ke dalam executable; output preprocessor terlihat seperti ini:

/* ... #included content from <stdio.h> ... */
int main(void)
{
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 4 + 1, 7 + 1, 5 + 1, 2 + 1, 6 + 1, 1 + 1, 3 + 1);
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 5 + 1, 7 + 1, 2 + 1, 6 + 1, 3 + 1, 1 + 1, 4 + 1);
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 6 + 1, 3 + 1, 5 + 1, 7 + 1, 1 + 1, 4 + 1, 2 + 1);
    /* ... 88 more solutions ... */
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           7 + 1, 3 + 1, 0 + 1, 2 + 1, 5 + 1, 1 + 1, 6 + 1, 4 + 1);
    return 0;
}

Itu bisa dilakukan, meskipun jelas tidak seharusnya.

kotak roti
sumber
7

Inilah solusi C ++ 11 tanpa templat apa pun:

constexpr int trypos(
    int work, int col, int row, int rows, int diags1, int diags2,
    int rowbit, int diag1bit, int diag2bit);

constexpr int place(
    int result, int work, int col, int row, int rows, int diags1, int diags2)
{
    return result != 0 ? result
        : col == 8 ? work
        : row == 8 ? 0
        : trypos(work, col, row, rows, diags1, diags2,
                 1 << row, 1 << (7 + col - row), 1 << (14 - col - row));
}

constexpr int trypos(
    int work, int col, int row, int rows, int diags1, int diags2,
    int rowbit, int diag1bit, int diag2bit)
{
    return !(rows & rowbit) && !(diags1 & diag1bit) && !(diags2 & diag2bit)
        ? place(
            place(0, work*10 + 8-row, col + 1, 0,
                  rows | rowbit, diags1 | diag1bit, diags2 | diag2bit),
            work, col, row + 1, rows, diags1, diags2)
        : place(0, work, col, row + 1, rows, diags1, diags2);
}

int places = place(0, 0, 0, 0, 0, 0, 0);

Solusinya dikodekan sebagai angka desimal, seperti dalam jawaban FredOverflow. GCC 4.7.1 mengkompilasi file di atas ke sumber rakitan berikut dengan g++ -S -std=c++11 8q.cpp:

    .file   "8q.cpp"
    .globl  places
    .data
    .align 4
    .type   places, @object
    .size   places, 4
places:
    .long   84136275
    .ident  "GCC: (GNU) 4.7.1"
    .section    .note.GNU-stack,"",@progbits

Nilai simbolnya placesadalah 84136275, yaitu ratu pertama pada a8, yang kedua pada b4 dll.

han
sumber
0

c ++ template, dengan hanya satu kelas template yang didefinisikan:

template <int N, int mask, int mask2, int mask3, int remainDigit, bool fail>
struct EQ;

template <int N, int mask, int mask2, int mask3>
struct EQ<N, mask, mask2, mask3, 0, false> {
    enum _ { Output = (char [N])1 };
};

template <int N, int mask, int mask2, int mask3, int i>
struct EQ<N, mask, mask2, mask3, i, true> { };

template <int N, int mask, int mask2, int mask3, int i>
struct EQ<N, mask, mask2, mask3, i, false> {
    enum _ { _ = 
             sizeof(EQ<N*10+1, mask|(1<<1), mask2|(1<<(1+i)), mask3|(1<<(1+8-i)), i-1, 
               (bool)(mask&(1<<1)) || (bool)(mask2&(1<<(1+i))) || (bool)(mask3&(1<<(1+8-i)))>) +
             sizeof(EQ<N*10+2, mask|(1<<2), mask2|(1<<(2+i)), mask3|(1<<(2+8-i)), i-1, 
               (bool)(mask&(1<<2)) || (bool)(mask2&(1<<(2+i))) || (bool)(mask3&(1<<(2+8-i)))>) +
             sizeof(EQ<N*10+3, mask|(1<<3), mask2|(1<<(3+i)), mask3|(1<<(3+8-i)), i-1, 
               (bool)(mask&(1<<3)) || (bool)(mask2&(1<<(3+i))) || (bool)(mask3&(1<<(3+8-i)))>) +
             sizeof(EQ<N*10+4, mask|(1<<4), mask2|(1<<(4+i)), mask3|(1<<(4+8-i)), i-1, 
               (bool)(mask&(1<<4)) || (bool)(mask2&(1<<(4+i))) || (bool)(mask3&(1<<(4+8-i)))>) +
             sizeof(EQ<N*10+5, mask|(1<<5), mask2|(1<<(5+i)), mask3|(1<<(5+8-i)), i-1, 
               (bool)(mask&(1<<5)) || (bool)(mask2&(1<<(5+i))) || (bool)(mask3&(1<<(5+8-i)))>) +
             sizeof(EQ<N*10+6, mask|(1<<6), mask2|(1<<(6+i)), mask3|(1<<(6+8-i)), i-1, 
               (bool)(mask&(1<<6)) || (bool)(mask2&(1<<(6+i))) || (bool)(mask3&(1<<(6+8-i)))>) +
             sizeof(EQ<N*10+7, mask|(1<<7), mask2|(1<<(7+i)), mask3|(1<<(7+8-i)), i-1, 
               (bool)(mask&(1<<7)) || (bool)(mask2&(1<<(7+i))) || (bool)(mask3&(1<<(7+8-i)))>) +
             sizeof(EQ<N*10+8, mask|(1<<8), mask2|(1<<(8+i)), mask3|(1<<(8+8-i)), i-1, 
               (bool)(mask&(1<<8)) || (bool)(mask2&(1<<(8+i))) || (bool)(mask3&(1<<(8+8-i)))>)};
};
int main(int argc, _TCHAR* argv[])
{
    // output all solutions to eight queens problems as error messages
    sizeof(EQ<0, 0, 0, 0, 8, false>);
    return 0;
}

jadi pesan kesalahan akan terlihat seperti:

error C2440: 'type cast': tidak dapat mengonversi dari 'int' ke 'char [15863724]'

DU Jiaen
sumber