2016-03-22 2 views
0

Я довольно новичок в Boost MPL (и мета-программировании в целом), и я думаю, что меня смущает идея шаблонов и типов. Простым примером, с которым я работаю, является попытка вычислить длину вектора. Следующий отлично компилируется:Boost MPL Types Vs Templates

typedef mpl::vector_c< int, 0, 1, 2, 3, 4, 5, 6, 7 > myVector; 

struct TestSize 
{ 
    template <typename mySequence> struct apply 
    { 
     typedef mpl::size<mySequence> type; 
    }; 
}; 

typedef TestSize::apply<myVector>::type result; 

, но если добавить «:: типа» к результату вычисления размера, как это:

struct TestSize 
{ 
    template <typename mySequence> struct apply 
    { 
     typedef mpl::size<mySequence>::type type; 
    }; 
}; 

typedef TestSize::apply<myVector>::type result; 

тогда я получаю сообщение об ошибке «Ошибка: нетиповая» подталкивание :: mpl :: size :: type [with Sequence = mySequence] "не является именем типа".

Это ситуация, когда параметр шаблона не выводится, потому что он находится в вложенном пространстве имен? Добавление к моей путаницы является тот факт, что следующие компилирует:

struct TestSize 
{ 
    template <typename mySequence> struct apply 
    { 
     typedef mpl::size<mySequence> type; 
     typedef mpl::range_c<int, 0, type::type::value> myRange; 
    }; 
}; 

typedef TestSize::apply<myVector>::type result; 
typedef TestSize::apply<textureIndices>::myRange range; 

Почему я могу сделать «тип :: Тип :: Значение» там, но не «размер < mySequence> :: тип» на линии раньше?

ответ

3

Причина вы испытываете эту ошибку, потому что вы должны использовать typename как это (во внутреннем apply):

struct TestSize 
{ 
    template <typename mySequence> struct apply 
    { 
     typedef typename mpl::size<mySequence>::type type; // <-- here! 
    }; 
}; 

Необходимость typename в этом контексте возникает от того, как составители компиляции шаблонов. Когда шаблон изначально предварительно скомпилирован, он должен быть семантически корректным. Однако компилятор не знает (на данный момент), что mpl::size<mySequence>::type действительно является типом. На данный момент он не знает, что такое mySequence, и как mpl::size указан для mySequence. И по умолчанию он принимает это не тип. Поэтому вам нужно намекнуть.

А теперь, вероятно, вы понимаете, почему type::type::value работает нормально - компилятор по умолчанию считает value не типом, вы не пытаетесь использовать его как тип, а компилятор счастлив. Кстати, если бы вы определили value как тип для определенной специализации, у вас была бы смешная ошибка компиляции, если эта специализация будет использована!

+1

@ user1777820, вы только что открыли такую ​​коробку Пандоры! Короче говоря, причина в том, что 'mpl :: size :: type' является * зависимым от шаблона * именем. Сематик 'type' будет отличаться от того, что на самом деле есть' T', это может быть функция, тип, переменная ... Все. С другой стороны, семантика 'size ' не зависит от 'T' - независимо от того, что такое' T', 'size ' - это только одно - это создание шаблона ранее определенного класса шаблона 'size'. Нет двусмысленности, поэтому не нужно намекать. – SergeyA

+0

Я удалил свой комментарий, так как я собирался начать новый вопрос, поэтому я добавляю его для тех, кто читает это в будущем. Я спрашивал, как решение здесь, используя подсказку typename, отличается от моего первого примера кода строкой «typedef mpl :: size type;» который компилируется отлично. Спасибо @SergeyA! – user1777820