Вспомогательная мета-функция вполне бы справилась:
template <typename C, typename M>
using PM = M C::*;
template<
class T2, class Array,
class PointerToMemberType = PM<typename std::decay_t<Array>::element, T2>
>
...
Что касается того, можно ли это сделать "напрямую", ответ - да, но вы должны опустить the typename
ключевое слово.Ваш компилятор должен принять это:
template<
class T2, class Array,
class PointerToMemberType = T2 std::decay_t<Array>::element::*
>
...
В соответствии со стандартом, [temp.res] / 5:
Полное имя, используемое в качестве имени в классе.-или-decltype (раздел 13) или уточненный спецификатор типа неявно предполагается для имени типа, без использования ключевого слова typename
.В спецификаторе вложенного имени , который непосредственно содержит спецификатор вложенного имени , который зависит от параметра шаблона, идентификатор или простой-шаблон-id подразумевается как имя типа без использования ключевого слова typename
.[ Примечание: Ключевое слово typename
не допускается синтаксисом этих конструкций.- конечная заметка ]
В нашей ситуации у нас есть спецификатор вложенного имени std::decay_t<Array>::element::
, который сразу же содержит вложенное имя-specifier std::decay_t<Array>::
, который зависит от параметра шаблона, поэтому этот абзац говорит нам, что typename
не требуется.Ясно, что когда за std::decay_t<Array>::element
следует ::
, компилятор знает, что std::decay_t<Array>::element
является типом, а не элементом данных или функцией-членом.
Согласно примечанию, грамматика запрещает ненужное использованиеtypename
в этой ситуации.Правильное использование спецификатора typename в соответствии с [temp.res] / 3:
typename
Спецификатор вложенного имени идентификатор
Здесь typename
применяется к идентификатору после применения всего спецификатора вложенного имени , например,в typename A::B::C::D
оператор ::
связывается более тесно, чем typename
, поэтому вы говорите, что typename A::B::C::D
является типом. спецификатор вложенного имени не может содержать typename
на верхнем уровне одного из его компонентов, поскольку из [expr.prim.id.qual] самый левый компонент может иметь тип -name , namespace-name или decltype-спецификатор и type-name (в отличие от type-id ) может быть только неквалифицированным именем или simple-template-id .Нелевые компоненты могут быть только неквалифицированными именами или simple-template-id s (иногда требуется префикс template
).