Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么调用总是取消引用数据成员,而不是在可能的情况下调用?_C++_Language Lawyer_C++17 - Fatal编程技术网

C++ 为什么调用总是取消引用数据成员,而不是在可能的情况下调用?

C++ 为什么调用总是取消引用数据成员,而不是在可能的情况下调用?,c++,language-lawyer,c++17,C++,Language Lawyer,C++17,这个问题()询问为什么INVOKE讨论数据成员,而忽略它们实际上是如何被调用的 这个问题()讨论了为什么要访问它们,但为什么在可调用时不调用它们 : 定义调用(f,t1,t2,…,tN),如下所示: (1.1)(t1.*f)(t2,…,tN)当f是指向类T的成员函数的指针且为uu-of v为真时 (1.2)(t1.get()*f)(t2,…,tN)当f是指向类T的成员函数的指针,而remove_-cvref_uuuuuut是引用包装器的特殊化 (1.3)((*t1)。*f)(t2,…,tN)当

这个问题()询问为什么INVOKE讨论数据成员,而忽略它们实际上是如何被调用的

这个问题()讨论了为什么要访问它们,但为什么在可调用时不调用它们

:

定义调用(f,t1,t2,…,tN),如下所示:

  • (1.1)(t1.*f)(t2,…,tN)当f是指向类T的成员函数的指针且为uu-of v为真时
  • (1.2)(t1.get()*f)(t2,…,tN)当f是指向类T的成员函数的指针,而remove_-cvref_uuuuuut是引用包装器的特殊化
  • (1.3)((*t1)。*f)(t2,…,tN)当f是指向类T的成员函数的指针,且t1不满足前两项时
  • (1.4)t1.*f,当N==1且f是指向类T的数据成员的指针且为“基”of“v”时为真
  • (1.5)当N==1且f是指向类T的数据成员的指针时,t1.get().*f,而remove­cvref­T是引用包装器的特殊化
  • (1.6)(*t1)。*f,当N==1且f是指向类T的数据成员的指针且t1不满足前两项时
  • (1.7)在所有其他情况下的f(t1,t2,…,tN)
1.4到1.6处理对指向数据成员的指针的访问,这对于给定函子和存储的可调用项是有意义的。我不明白的是,为什么它不给这些成员打电话,而是简单地取消对他们的引用?我希望1.4将与1.1的语法并行,并且如果
f
拥有
操作符()
,则调用所讨论的对象

为什么会有这样的限制?它有什么作用


下面是一些需要澄清的代码:

#include <functional>
#include <iostream>

struct func1 
{ 
    void operator()() { std::cout << "Invoked functor\n"; }
};

void func2()
{
    std::cout << "Invoked free function\n";
}

struct D1 {};

struct T1 {
    func1 f1;
    void func3() { std::cout << "Invoked member function\n"; }
    D1 d1;
};

int main()
{
    T1 t1;
    func1 free_f1;
    std::invoke(&T1::f1, t1);               //does nothing
    std::invoke(&func1::operator(), t1.f1); //okay, so there is a workaround, if clumsy
    std::invoke(&func2);                    //calls func2
    std::invoke(&T1::func3, t1);            //calls func3
    std::invoke(&T1::d1, t1);               //does nothing (expected)
    std::invoke(free_f1);                   //works on non-member functors

    return 0;
}
#包括
#包括
结构函数1
{ 

void operator(){std::cout在组装C++11的标准库时,它具有来自各种Boost库的许多功能。在本次对话中,以下Boost工具很重要:

  • bind
  • 功能
  • reference\u包装器
  • mem\u fn
在某种程度上,它们都与一个可调用的东西相关,这个东西可以接受一些类型的参数,并产生一个特定的返回值。因此,它们都试图以一致的方式处理可调用的东西。C++11在采用这些工具时,根据完美的转发规则发明了
调用
的概念,以便所有这些都能够参考一致的处理方式

mem\u fn
的唯一目的是获取指向成员的指针,并将其转换为可直接使用
()
。对于指向成员函数的指针,最明显的做法是调用所指向的成员函数,给定该函数的对象和任何参数。对于指向成员变量的指针,最明显的做法是返回该成员变量的值,给定要访问的对象

将数据成员指针转换为返回变量本身的一元函子的功能非常有用。您可以使用类似于
std::transform
的方法,将数据成员指针的
mem\u fn
传递给它,以生成访问特定可访问数据成员的值序列。添加到C++20的范围功能将使其更加有用,因为您可以创建变换范围,只需获取成员指针即可操作子对象序列

但问题是:无论成员子对象的类型如何,您都希望它能够工作。如果该子对象恰好是可调用的,
mem\u fn
应该能够像访问任何其他对象一样访问可调用对象。它恰好是可调用的事实与
mem\u fn
的用途无关

但是
boost::function
boost::bind
可以使用成员指针。它们都基于
boost::mem\u fn
的成员指针行为。因此,如果
mem\u fn
将指向数据成员的指针视为返回该成员值的一元函子,那么所有这些都必须将指向数据成员的指针视为一个数据指针那样的话

因此,当C++11将所有这些编码成一个统一的概念时,它将实践直接编码成
INVOKE

所以从词源学的角度来看,这就是为什么
INVOKE
是这样工作的:因为所有这些都意味着以相同的方式对待可调用项,
mem_fn
关于数据成员指针的全部要点是将它们视为返回其值的一元函数。所以其他人也必须这样对待它们


这难道不是一件好事吗?这不是正确的行为吗?如果成员指针指向的类型恰好可以调用,那么您真的想让指向数据成员的指针的行为与不可调用的指针的行为大不相同吗?这将使编写接受数据成员指针的通用代码变得不可能,然后对某些序列进行操作对象。如果您不确定数据成员指针是否会得到引用的子对象或调用子对象本身,那么如何才能常规地访问该数据成员指针?

一般来说,数据不是可以调用的对象。@eerorika存储的lambda和函数对象可以。它对所有类型的成员都有意义,而不仅仅是对函子。这是在链接的问题中解释的,所以我认为链接的问题是完全重复的,不是吗?您可以执行
struct X{int n;};std::function f(&X::n);
现在,
f(X)
返回
X.n
。注意
&X::n
是指向数据成员的普通指针,而不是可调用的指针。这就是用法
(1.4)
支持。
(1.5)
(1.6)
留给读者作为练习。@IgorTandetnik是的,这在链接的问题中,但这并不能让我更接近这个问题的答案。