Löse das Acht-Damen-Problem beim Kompilieren [geschlossen]

39

Kannst du das Acht-Königinnen-Rätsel beim Kompilieren lösen ?

Wählen Sie ein geeignetes Ausgabeformat.

Ich bin besonders an einer Metaprogrammierungslösung für C ++ - Vorlagen interessiert, aber Sie können Sprachen verwenden, die ähnliche Konstrukte haben, wie zum Beispiel das Typensystem von Haskell.

Idealerweise würde Ihr Metaprogramm alle Lösungen ausgeben. Keine Hardcodierung.

R. Martinho Fernandes
quelle
Warum erlaubst du nicht verschiedene Sprachen?
Benutzer unbekannt
@user: Weil ich an einer C ++ TMP-Lösung interessiert bin. Wenn Sie eine Sprache kennen, die sehr ähnliche Konstrukte hat, können Sie eine Antwort schreiben.
R. Martinho Fernandes
Kann ich auch das Typensystem von Haskell verwenden? AFAIK sollte es vollständig sein.
FUZxxl
@FUZxxl: Ja. Ich werde die Frage bearbeiten.
R. Martinho Fernandes
Reicht es aus, die Brute-Force-Lösung durchzuführen?
aufgehört, gegen den Uhrzeigersinn

Antworten:

50

Mein Metaprogramm findet alle 92 Lösungen. Sie werden als Fehlermeldungen ausgegeben:

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

Dies bedeutet, dass die erste Dame bei y = 1, die zweite bei y = 5, die dritte bei y = 8 usw. platziert werden sollte.

Zunächst einige nützliche Metafunktionen:

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

Dann zwei interessante Metafunktionen (beachten Sie den Singular und den Plural):

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

Die Variable queensspeichert die y-Koordinaten der bisher auf der Tafel platzierten Damen. Die folgenden drei Variablen speichern die Zeilen und Diagonalen, die bereits von Königinnen belegt sind. xund ysollte selbsterklärend sein.

Das erste Argument, um zu if_then_elseprüfen, ob die aktuelle Position gesperrt ist. Wenn dies der Fall ist, stoppt die Rekursion, indem das (bedeutungslose) Ergebnis 0 zurückgegeben wird. Andernfalls wird die Dame auf die Tafel gelegt und der Vorgang wird mit der nächsten Spalte fortgesetzt.

Wenn x 8 erreicht, haben wir eine Lösung gefunden:

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

Da die printVorlage kein Mitglied hat solution, generiert der Compiler einen Fehler.

Um den Prozess zu starten, inspizieren wir schließlich das valueMitglied der leeren Tafel:

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

Das komplette Programm finden Sie bei ideone .

fredoverflow
quelle
2
Ich mag: 1) die Verwendung von Bitfeldern zum Speichern von Daten, 2) die Wahl der Ausgabemethode.
R. Martinho Fernandes
7
Zu großartig für eine Antwort.
st0le
Soll es nicht auch die x-Werte ausgeben?
DeadMG
2
@DeadMG Der x-Wert jeder Queen-Position ist ihre Position in der Zeichenfolge (1-8).
Briguy37
22

Ich habe eine Lösung gefunden, die das Haskell-System verwendet. Ich habe ein wenig nach einer vorhandenen Lösung für das Problem auf der Wertebene gegoogelt , sie ein wenig geändert und sie dann auf die Typebene angehoben. Es bedurfte einer Menge Neuerfindungen. Ich musste auch eine Reihe von GHC-Erweiterungen aktivieren.

Erstens, da Ganzzahlen auf Typebene nicht zulässig sind, musste ich die natürlichen Zahlen noch einmal neu erfinden, diesmal als Typen:

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

Der Algorithmus, den ich angepasst habe, addiert und subtrahiert Naturals, daher musste ich diese ebenfalls neu erfinden. Funktionen auf Typebene werden mit Rückgriff auf Typklassen definiert. Dies erfordert die Erweiterungen für mehrere Parametertypklassen und funktionale Abhängigkeiten. Typklassen können keine "Werte zurückgeben", daher verwenden wir einen zusätzlichen Parameter, ähnlich wie bei 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

Die Rekursion wird mit Zusicherungen von Klassen implementiert, sodass die Syntax etwas rückständig wirkt.

Als nächstes waren Booleaner:

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

Und eine Funktion zum Vergleichen von Ungleichungen:

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

Und Listen ...

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 fehlen auch auf der Typebene ...

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

Und damit waren alle unterstützenden Maschinen, die ich benutzte, an Ort und Stelle. Zeit, das Problem selbst anzugehen!

Beginnen Sie mit einer Funktion, um zu testen, ob das Hinzufügen einer Dame zu einem vorhandenen Board in Ordnung ist:

-- 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)]

Beachten Sie die Verwendung von Class Assertions, um Zwischenergebnisse zu erhalten. Da die Rückgabewerte tatsächlich ein zusätzlicher Parameter sind, können wir die Zusicherungen nicht einfach direkt voneinander aufrufen. Wenn Sie PROLOG bereits verwendet haben, ist Ihnen dieser Stil möglicherweise ein wenig vertraut.

Nachdem ich einige Änderungen vorgenommen hatte, um die Notwendigkeit von Lambdas zu beseitigen (die ich hätte implementieren können, aber ich beschloss, für einen anderen Tag zu gehen), sah die ursprüngliche Lösung folgendermaßen aus:

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]

mapist eine Funktion höherer Ordnung. Ich dachte, das Implementieren von Meta-Funktionen höherer Ordnung wäre zu mühsam (wieder Lambdas), also entschied ich mich für eine einfachere Lösung: Da ich weiß, welche Funktionen abgebildet werden, kann ich mapfür jede spezielle Versionen implementieren , so dass dies nicht der Fall ist Funktionen höherer Ordnung.

-- 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)

Und die letzte Meta-Funktion kann jetzt geschrieben werden:

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

Alles, was bleibt, ist eine Art Fahrer, der die Maschinen zur Typprüfung überredet, die Lösungen zu erarbeiten.

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

Dieses Metaprogramm soll auf dem Type Checker laufen, so dass man starten und nach dem Typ ghcifragen kann queens eight:

> :t queens eight

Dies wird die Standard-Rekursionsgrenze ziemlich schnell überschreiten (es ist eine dürftige 20). Um dieses Limit zu erhöhen, müssen wir ghcimit der -fcontext-stack=NOption aufrufen , wo Ndie gewünschte Stapeltiefe ist (N = 1000 und 15 Minuten sind nicht genug). Ich habe diesen Lauf noch nicht vollständig gesehen, da er sehr lange dauert, aber ich habe es geschafft, ihn zu erreichen queens four.

Es gibt ein volles Programm auf ideone mit einigen Maschinen zum hübschen Drucken der Ergebnistypen, aber es queens twokann nur ausgeführt werden, ohne die Grenzen zu überschreiten :(

R. Martinho Fernandes
quelle
Neben einer interessanten Lösung ist dies eine spaßige Referenz dessen, was mit Klassen- /
Michael Klein,
11

C über den Präprozessor

Ich denke, das ANSI-Komitee hat sich bewusst dafür entschieden, den C-Präprozessor nicht so weit zu erweitern, dass er vollständig ist. In jedem Fall ist es nicht stark genug, um das Acht-Königinnen-Problem zu lösen. Nicht in irgendeiner allgemeinen Weise.

Dies ist jedoch möglich, wenn Sie bereit sind, die Schleifenzähler fest zu codieren. Natürlich gibt es keine echte Möglichkeit, eine Schleife zu erstellen, aber Sie können die Selbsteinbeziehung (über #include __FILE__) verwenden, um eine begrenzte Art von Rekursion zu erhalten.

#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

Trotz der schrecklichen Menge an sich wiederholenden Inhalten kann ich Ihnen versichern, dass das Acht-Königinnen-Problem damit wirklich algorithmisch gelöst wird. Leider konnte ich mit dem Präprozessor nur eine allgemeine Push-Down-Stack-Datenstruktur implementieren. Das Ergebnis ist, dass ich den Wert von dort, iwo er verwendet wurde , fest codieren musste , um einen anderen einzustellenden Wert auszuwählen. (Im Gegensatz zum Abrufen von Werten, was ganz allgemein möglich ist. Aus diesem Grund musste der #ifobere Bereich der Datei, der darüber entscheidet, ob eine Dame an der aktuellen Position hinzugefügt werden kann, nicht acht Mal wiederholt werden.)

Im Präprozessor Code, iund jzeigt die aktuelle Position in Betracht gezogen werden, während r, pund nzu verfolgen, welche Reihen und Diagonalen sind derzeit nicht verfügbar für die Platzierung. Doppelt sich jedoch iauch als Indikator für die aktuelle Rekursionstiefe, sodass in Wirklichkeit alle anderen Werte i als eine Art Index verwenden, sodass ihre Werte erhalten bleiben, wenn eine Rekursion fortgesetzt wird. (Und auch wegen der ernsthaften Schwierigkeit, den Wert eines Präprozessorsymbols zu ändern, ohne es vollständig zu ersetzen.)

Das kompilierte Programm druckt alle 92 Lösungen. Die Lösungen sind direkt in die ausführbare Datei eingebettet. Die Ausgabe des Präprozessors sieht folgendermaßen aus:

/* ... #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;
}

Es kann getan werden, auch wenn es eindeutig nicht sollte.

Brot-Box
quelle
7

Hier ist eine C ++ 11-Lösung ohne Vorlagen:

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

Die Lösung wird wie in FredOverflows Antworten als Dezimalziffern codiert. GCC 4.7.1 kompiliert die obige Datei in die folgende Assembly-Quelle mit 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

Der Wert des Symbols placesist 84136275, dh die erste Dame ist bei a8, die zweite bei b4 usw.

han
quelle
0

c ++ template, wobei nur eine Template-Klasse definiert ist:

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

Die Fehlermeldung sieht dann so aus:

Fehler C2440: 'Typumwandlung': Umwandlung von 'int' in 'char [15863724]' nicht möglich

DU Jiaen
quelle