2016-06-24 2 views
2

У меня есть несколько битмаксов для добавления (layer, logical OR |), но поскольку они являются константами, я бы хотел сделать это во время компиляции. Ввод передовой территории шаблона ...Добавление битовой маски компиляции в C++

Я попытался рекурсии:

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

, который дал следующие ошибки:

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 { 
     ^

Я также пробовал этот странный синтаксис, задаваемой (предположительно) непонимание страницы cppreference по адресу parameter packs:

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

который бросил эти ошибки:

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

У меня есть ощущение, решение находится где-то в template<template< области ада, если кто-нибудь может объяснить тем, я был бы признателен.

+1

Последний (маскирует ...) в настоящее время даже не C++ 17 (AFAIK), есть большие надежды получить его .. когда-то. Кроме того, непонятно, почему вы не просто ИЛИ значения. Когда обе стороны '' 'являются константами времени компиляции, компилятор может - и будет - оптимизировать его. – lorro

+0

Вы попробовали 'constexpr'? Также я подозреваю, что если вы просто сделаете их 'const', то компилятор все равно выполнит математику во время компиляции. – Galik

+0

Хорошие очки @lorro и Galik, я думаю, у меня нет такой веры в компилятор. – Kisss256

ответ

3

Вы опечатка (ы) в этом выражении:

masks | MaskAdd<masks>::value 

Оно должно быть:

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

Тогда он будет жаловаться на переопределение класса, поэтому обеспечить специализацию вместо (для один параметр):

template <uint8_t mask> 
struct MaskAdd<mask> { .. }; 
+0

Проверено. Извините за эту глупую опечатку. Этот синтаксис специализации - это то, что я должен изучить. – Kisss256

+0

Как я могу расширить это решение для обработки разных типов, но все равно использовать тот же синтаксис 'MaskAdd :: value'? – Kisss256

+0

@ Kisss256 Я сделал это как [это] (http://coliru.stacked-crooked.com/a/2cc09e46cb6a914c). Вы можете сделать это с помощью 'class', но тип должен быть первым параметром. Будет лучше, если вы посмотрите на 'constexpr'. – LogicStuff

Смежные вопросы