2016-06-24 12 views
2

Ich habe eine Reihe von Bitmasken hinzufügen (Schicht, logische OR |), aber wie sie Konstanten sind möchte ich dies zur Kompilierzeit tun. Die Eingabe erweitert Vorlage Gebiets ...C++ Kompilierzeit Bitmaske Addition

Ich versuchte Rekursion:

template <uint8_t mask, uint8_t...masks> 
struct MaskAdd { 
    static const uint8_t value = masks | MaskAdd<masks>::value; 
}; 

template <uint8_t mask> 
struct MaskAdd { 
    static const uint8_t value = mask; 
}; 

, die folgenden Fehler gab:

file.cpp:3:55: error: parameter packs not expanded with ‘...’: 
    static const uint8_t value = masks | MaskAdd<masks>::value; 
                ^
file.cpp:3:55: note:   ‘masks’ 
file.cpp:7:8: error: redeclared with 1 template parameter 
struct MaskAdd { 
     ^
file.cpp:2:8: note: previous declaration ‘template<unsigned char mask, unsigned char ...masks> struct MaskAdd’ used 2 template parameters 
struct MaskAdd { 
     ^

ich diese seltsame Syntax auch versucht, durch (vermutlich) ein Missverständnis der cppreference Seite auf parameter packs:

template <uint8_t...masks> 
struct MaskAdd { 
    static const uint8_t value = (masks | ...); 
}; 

, die diese Fehler warf:

file.cpp:3:43: error: expected primary-expression before ‘...’ token 
    static const uint8_t value = (masks | ...); 
             ^
file.cpp:3:43: error: expected ‘)’ before ‘...’ token 

ich in der template<template< Region der Hölle irgendwo haben, ist die Lösung für ein Gefühl, wenn jemand diejenigen erklären kann ich dankbar sein würde.

+1

Letzteres (Masken | ...) ist derzeit nicht einmal C++ 17 (AFAIK), es gibt große Hoffnungen, es zu bekommen .. irgendwann. Es ist auch nicht klar, warum Sie nicht nur die Werte ODER. Wenn beide Seiten von '|' Kompilierzeitkonstanten sind, kann und wird der Compiler es optimieren. – lorro

+0

Haben Sie 'constexpr' versucht? Ich vermute auch, wenn Sie sie nur "const" machen, wird der Compiler die Mathematik sowieso zur Kompilierzeit tun. – Galik

+0

Gute Punkte @lorro und Galik, ich glaube, ich habe nicht so viel Vertrauen in den Compiler. – Kisss256

Antwort

3

Sie haben Typo (s) in diesem Ausdruck:

masks | MaskAdd<masks>::value 

Es sollte:

mask | MaskAdd<masks...>::value 
//^no 's'  ^the expansion compiler was talking about 

Dann wird es über die Neudeklaration der Klasse klagen, so stattdessen eine Spezialisierung bieten (für ein einzelner Parameter):

+0

überprüft. Sorry für diesen dummen Tippfehler. Diese Spezialisierung Syntax ist etwas, was ich untersuchen muss. – Kisss256

+0

Wie könnte ich diese Lösung erweitern, um verschiedene Typen zu behandeln, aber immer noch die gleiche 'MaskAdd :: value' Syntax? – Kisss256

+0

@ Kisss256 Ich habe es getan wie [das] (http://coliru.stacked-crooked.com/a/2cc09e46cb6a914c). Sie könnten es mit einer 'Klasse' machen, aber der Typ müsste der erste Parameter sein. Es wird besser sein, wenn Sie in "constexpr" schauen. – LogicStuff