将指针的类型写入其他模板类型的成员数据
Write the type of a pointer to member data from other template types
我有一个函数可以从其他类型中提取指向成员类型的指针,这个函数有效:
template<class T2, class Array,
class Element = typename std::decay_t<Array>::element,
class PointerToMemberType = T2 Element::*
>
v f(Array&& a, PointerToMemberType pm);
但是我找不到写PointerToMemberType = ???
的方法,而不先定义Element
,应该可以省略。
如何不使用助记符Element
直接写PointerToMemberType
?
我尝试了简单的替换,但它不起作用:
template<
class T2, class Array,
class PointerToMemberType = T2 typename std::decay_t<Array>::element::*
>
void f(Array&&, PointerToMemberType pm);
// error: expected identifier before ‘*’ token
677 | class PointerToMemberType = T2 typename std::decay_t<Array>::element::*
^
我也尝试在几个地方添加 typename
和括号。
请注意,PointerToMemberType
目前不用于扣除,尽管我将来会尝试使用它。
在某些地方,它建议使用 std::invoke
这样就不需要处理指向数据成员的指针,这将如何适合或简化这里的内容?
辅助元函数可以很好地完成此任务:
template <typename C, typename M>
using PM = M C::*;
template<
class T2, class Array,
class PointerToMemberType = PM<typename std::decay_t<Array>::element, T2>
>
...
至于能不能做到"directly",答案是可以的,但是一定要省略 typename
关键字。你的编译器应该接受这个:
template<
class T2, class Array,
class PointerToMemberType = T2 std::decay_t<Array>::element::*
>
...
按照标准,[temp.res]/5:
A qualified name used as the name in a class-or-decltype (Clause 13) or an elaborated-type-specifier is
implicitly assumed to name a type, without the use of the typename
keyword. In a nested-name-specifier
that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or
simple-template-id is implicitly assumed to name a type, without the use of the typename
keyword. [ Note:
The typename
keyword is not permitted by the syntax of these constructs. — end note ]
在我们的情况下,我们有 nested-name-specifier std::decay_t<Array>::element::
,它立即包含 nested-name-specifier std::decay_t<Array>::
这取决于一个模板参数,所以这一段告诉我们 typename
不是必需的。显然,当 std::decay_t<Array>::element
后跟 ::
时,编译器知道 std::decay_t<Array>::element
是一个类型,而不是数据成员或成员函数。
根据注释,语法禁止在这种情况下不必要地使用 typename
。根据 [temp.res]/3 正确使用 typename-specifier 是:
typename
nested-name-specifier identifier
这里,typename
在整个nested-name-specifier被应用之后应用到标识符,例如,在 typename A::B::C::D
中,::
运算符比 typename
绑定得更紧密,所以你说 typename A::B::C::D
是一种类型。 nested-name-specifier 不能在其组件之一的顶层包含 typename
,因为从 [expr.prim.id.qual] 开始,最左边的组件只能是type-name,一个namespace-name,或者一个decltype-specifier , 而 type-name(不同于 type-id)只能是一个不合格的名称或 simple-template-id。 Non-leftmost组件只能是非限定名称或simple-template-ids(有时需要加上template
前缀)。
我有一个函数可以从其他类型中提取指向成员类型的指针,这个函数有效:
template<class T2, class Array,
class Element = typename std::decay_t<Array>::element,
class PointerToMemberType = T2 Element::*
>
v f(Array&& a, PointerToMemberType pm);
但是我找不到写PointerToMemberType = ???
的方法,而不先定义Element
,应该可以省略。
如何不使用助记符Element
直接写PointerToMemberType
?
我尝试了简单的替换,但它不起作用:
template<
class T2, class Array,
class PointerToMemberType = T2 typename std::decay_t<Array>::element::*
>
void f(Array&&, PointerToMemberType pm);
// error: expected identifier before ‘*’ token
677 | class PointerToMemberType = T2 typename std::decay_t<Array>::element::*
^
我也尝试在几个地方添加 typename
和括号。
请注意,PointerToMemberType
目前不用于扣除,尽管我将来会尝试使用它。
在某些地方,它建议使用 std::invoke
这样就不需要处理指向数据成员的指针,这将如何适合或简化这里的内容?
辅助元函数可以很好地完成此任务:
template <typename C, typename M>
using PM = M C::*;
template<
class T2, class Array,
class PointerToMemberType = PM<typename std::decay_t<Array>::element, T2>
>
...
至于能不能做到"directly",答案是可以的,但是一定要省略 typename
关键字。你的编译器应该接受这个:
template<
class T2, class Array,
class PointerToMemberType = T2 std::decay_t<Array>::element::*
>
...
按照标准,[temp.res]/5:
A qualified name used as the name in a class-or-decltype (Clause 13) or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the
typename
keyword. In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of thetypename
keyword. [ Note: Thetypename
keyword is not permitted by the syntax of these constructs. — end note ]
在我们的情况下,我们有 nested-name-specifier std::decay_t<Array>::element::
,它立即包含 nested-name-specifier std::decay_t<Array>::
这取决于一个模板参数,所以这一段告诉我们 typename
不是必需的。显然,当 std::decay_t<Array>::element
后跟 ::
时,编译器知道 std::decay_t<Array>::element
是一个类型,而不是数据成员或成员函数。
根据注释,语法禁止在这种情况下不必要地使用 typename
。根据 [temp.res]/3 正确使用 typename-specifier 是:
typename
nested-name-specifier identifier
这里,typename
在整个nested-name-specifier被应用之后应用到标识符,例如,在 typename A::B::C::D
中,::
运算符比 typename
绑定得更紧密,所以你说 typename A::B::C::D
是一种类型。 nested-name-specifier 不能在其组件之一的顶层包含 typename
,因为从 [expr.prim.id.qual] 开始,最左边的组件只能是type-name,一个namespace-name,或者一个decltype-specifier , 而 type-name(不同于 type-id)只能是一个不合格的名称或 simple-template-id。 Non-leftmost组件只能是非限定名称或simple-template-ids(有时需要加上template
前缀)。