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

标签 c++ c++11 pointer-to-member

我有一个函数可以从其他类型中提取指向成员类型的指针,并且可以正常工作:

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 the typename keyword. [ Note: The typename 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-namedecltype-specifiertype-name(与 type-id 不同)只能是非限定名称或 em>简单模板 ID。非最左边的组件只能是非限定名称或simple-template-id(有时需要以 template 为前缀)。

关于c++ - 将指针的类型写入其他模板类型的成员数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56821610/

相关文章:

c++ - 与 c++ 中的删除功能混淆

使用夹具的 C++ GoogleTest - 函数指针定义不可访问

c++ - 从指针到成员的映射

c++ - 如何在现代 C++ 中基于另一组可变参数模板参数来表示可变参数模板类型?

c++ - 如何初始化具有特定数量元素的集合?

c++ - 用于 C++ 运算符重载的 Python 绑定(bind)

c++ - 升压序列化: specifying a template class version

c++ - C++11 中具有 C 链接的复杂类型

c++ - 如何将成员函数模板作为模板参数传递?

c++ - 程序崩溃时如何释放资源