2010-05-25 3 views
6

Можно ли использовать параметр шаблона константы без типа в директиве препроцессора? Вот что я имею в виду:Использовать параметр шаблона в директиве препроцессора?

template <int DING> 
struct Foo 
{ 
    enum { DOO = DING }; 
}; 

template <typename T> 
struct Blah 
{ 
    void DoIt() 
    { 
     #if (T::DOO & 0x010) 

     // some code here 

     #endif 
    } 
}; 

Когда я попробовать это с чем-то вроде Blah<Foo<0xFFFF>>, VC++ 2010 жалуется на что-то о несовпадающих скобках в строке, где мы пытаемся использовать #if. Я предполагаю, что препроцессор действительно ничего не знает о шаблонах, и такого рода вещи просто не в его области. Что сказать?

+0

Просто следует отметить: 'Бла >' не будет разбирать в текущем C++, вам нужно пространство между '>' ы. 'Blah >'. – KitsuneYMG

+0

Собственно, в VC++ 2010 он компилируется! :) Они частично реализовали C++ 0x в VC++ 2010. – Raj

ответ

11

Нет, это невозможно. Препроцессор довольно тупой, и он не знает структуру вашей программы. Если T::Doo не определено в препроцессоре (и этого не может быть из-за ::), он не может оценить это выражение и не сработает.

Однако, вы можете положиться на компилятор, чтобы сделать умные вещи для вас:

 if (T::Doo & 0x010) { 
      // some code here 
     } 

Постоянные выражения и мертвые ветви оптимизированы прочь даже при более низких настройках оптимизации, так что вы смело можете сделать это без каких-либо время выполнения.

+0

Не будет ли это не скомпилировано, если 'Doo' нет в' T'? –

+0

Спасибо. Это то, о чем я думал. Использование компилятора, однако, не идеально для меня, потому что то, что члены доступны в 'T', зависит от того, какие биты установлены в' T :: DOO'. Я уверен, что приближаюсь к этому неправильно. Я покажу что-то еще. Но было просто интересно, как далеко мы можем пойти с препроцессором. Другим вариантом может быть просмотр того, можно ли использовать трюки мета-программирования шаблона для этого. – Raj

+0

Они, вероятно, могут. Если вы откроете новый вопрос с подробностями того, что вы хотите выполнить, мы можем посмотреть. – Thomas

2

какие члены доступны в T зависит от того, какие биты установлены в T::DOO

Это звучит для меня как T::DOO действует как идентификатор подкласса. Поэтому я думаю, что ваш Foo и связанные классы должны быть подклассами класса, который гарантирует, что определено значение DOO.

Ключ: почему вы должны использовать поле бит?

+0

Ответ на этот вопрос немного связан, но вы совершенно правы. Я работаю с этим API (DirectX), который позволяет определенную гибкость в определении того, как вы хотите отформатировать содержимое определенной структуры, которая передается в качестве входных данных для одного из его методов. Информация о том, как вы устанавливаете структуру, передается через бит-поле. В моем приложении у меня есть 2 абстракции - первый - это шаблонный класс, который генерирует коллекцию экземпляров этой структуры с битовым полем, а сама структура передается как аргументы шаблона, а другая - эта коллекция. Комментарий contd.ниже – Raj

+0

Я хотел написать некоторый условный код в классе потребителя, который использовал определенные элементы этой структуры, проверяя, какие биты установлены в бит-поле. Уф! Я не уверен, насколько это имело смысл! Поскольку существуют различные шаблонные экземпляры исходного класса, сопоставленные с различными вариантами структуры, соответствующий код должен быть скомпилирован с условием - следовательно, идея попытаться определить, можно ли использовать препроцессор. – Raj

1

Не уверен, что это относится к вашей ситуации, но можно выделить различные случаи с помощью классов шаблонов. Например: (используя модифицированную версию кода из выше)

template <typename T, int N> 
struct Blah 
{ 
    void DoIt() 
    { 
     // normal DoIt() code 
    } 
}; 

template <typename T> 
struct Blah<T,5> 
{ 
    void DoIt() 
    { 
     // special DoIt() code for only when N==5 
    } 
};