我有一个函数可以从其他类型中提取指向成员类型的指针,并且可以正常工作:
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
, 应该可以省略。
我怎么写PointerToMemberType
直接不使用辅助Element
?
我尝试了普通替换,但它不起作用:
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>
>
...
至于是否可以“直接”完成,答案是肯定的,但必须省略 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 ]
在我们的情况下,我们有嵌套名称说明符 std::decay_t<Array>::element::
其中立即包含嵌套名称说明符 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
绑定(bind)得更紧密,所以你说的是 typename A::B::C::D
是一种类型。 nested-name-specifier 不能包含 typename
在其组件之一的顶层,因为从 [expr.prim.id.qual] 开始,最左边的组件只能是一个type-name,一个namespace-name 或 decltype-specifier 和 type-name(与 type-id 不同)只能是非限定名称或 em>简单模板 ID。非最左边的组件只能是非限定名称或simple-template-id(有时需要以 template
为前缀)。
关于c++ - 将指针的类型写入其他模板类型的成员数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56821610/