将指针的类型写入其他模板类型的成员数据

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前缀)。