【问题标题】:Member Variable Pointer成员变量指针
【发布时间】:2014-07-25 02:01:50
【问题描述】:

对于给定的结构:

struct foo
{
    void fooFunc(){}
    int fooVar = 0;
};

我可以为函数创建一个调用 wapper:std::mem_fn( &foo::fooFunc ),这样我就可以将它传递给另一个方法并在对象上调用它。
我想知道是否有类似的调用包装器,但用于成员变量。

例如,我在这里使用指向成员变量的指针,但我想使用调用包装器:

void bar( std::function< void( foo ) > funcPtr, int foo::* varPtr )
{
    foo myFoo;
    funcPtr( myFoo );
    foo.*varPtr = 13;
}

【问题讨论】:

  • @WilliamAndrewMontgomery 实际上我已经查看了C++: Pointer to class data member 没有 STL 构造。
  • 成员变量指针不是“C风格”。
  • 您的问题中没有任何内容来自“STL
  • 你想完成什么?
  • C 不支持指向成员的指针,因此将其称为 C 风格绝对不是最清楚的表达方式!您想要的术语是 mem_fn 返回的“调用包装器”和 int foo::* 的“指向成员的指针”

标签: c++ c++11 wrapper member-pointers mem-fun


【解决方案1】:

注意您的问题中没有任何内容来自 STL(这是 1990 年代的库),std::functionstd::mem_fn 是 C++ 标准库的一部分,这不是一回事。

std::mem_fn支持成员函数和成员变量,所以你可以这样做来访问成员变量并设置它:

foo f;
std::function<int&(foo&)> var( std::mem_fn( &foo::fooVar ) );
var(f) = 1;

【讨论】:

  • 根据en.wikipedia.org/wiki/Standard_Template_Library,“功能”绝对是STL的一部分。
  • @isarandi,但std::functionstd::mem_fn 不是,它们是 C++11 中的新内容,来自 Boost,而不是来自 STL。仅仅因为它们与其他东西在同一个标​​题中并不能使它们相同。
  • 但这只是 STL 的新版本,对吧? STL 是 C++ 标准库的一部分。 std::function 位于 C++11 标准库的 STL 部分。至少维基百科是这样对待它的。它来自哪里与现在的位置无关。
  • 不,这不正确,也不是维基百科所说的。 STL 的部分内容已合并到 C++ 标准库中(但不是全部),其他内容稍后已合并到 C++ 标准库中。不过,那些其他的东西并没有成为 STL 的一部分。例如,std::functionstd::mem_fn 不是 sgi.com/tech/stl 的一部分。
  • 不,问题是你不能从参数中推断出T。请参阅类似的stackoverflow.com/a/23900128/981959。您不能从不是std::function&lt;T&amp;(foo&amp;)&gt; 的东西中推断出std::function&lt;T&amp;(foo&amp;)&gt; 中的T,因为可能允许推导成功的可能转换集是无限的,并且编译器无法处理无穷大(这不是这次你的编译器有问题,我的编译器也无法处理无穷大:-)
【解决方案2】:

除了成员函数,std::mem_fn 也可以包装数据成员,并允许对它们进行读取访问。所以以下工作:

void print_fooVar(foo& f, std::function<int(foo)> varAccess)
{
    std::cout << varAccess(f) << std::endl;
}

foo f;
print_fooVar(f, std::mem_fn(&foo::fooVar)); // prints 0

正如 JonathanWakely 在 cmets 中提到的,您可以使用 mem_fn 本身返回的(未指定)类型来设置数据成员。

foo f;
std::mem_fn(&foo::fooVar)(f) = 13;

或者将其转换为std::function 使用

void bar( foo& f, std::function<int&(foo&)> fooVarSet )
{
    fooVarSet(f) = 26;
}

如果您正在寻找一种方法来生成可调用以设置 fooVar 数据成员,而不是专门使用 std::mem_fn 来执行此操作,您也可以使用 lambda 表达式完成工作。

void bar( foo& f, std::function<void(foo)> funcPtr, 
                  std::function<void(foo&, int)> fooVarSet )
{
    funcPtr( f );
    fooVarSet(f, 13);
}

foo f;
bar(f, std::mem_fn(&foo::fooFunc), [](foo& f, int i) {f.fooVar = i;});

Live demo

【讨论】:

  • mem_fn 在成员变量上返回一个引用,所以你可以只到mem_fn(&amp;foo::fooVar)(f) = 1;
  • @JonathanWakely 确实如此,我应该更清楚地回答。我不知道如何将mem_fn 返回的任何类型转换为std::function,然后可用于设置数据成员。我会编辑答案。
  • 哦,这很简单,只需将其存储在std::function&lt;int&amp;(foo&amp;)&gt;
  • @JonathanWakely 我试过std::function&lt;int&amp;(foo)&gt;,但没有成功。很近!谢谢指点。
猜你喜欢
  • 1970-01-01
  • 2018-03-07
  • 2011-02-07
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多