有什么方法可以创建以成员函数或成员作为参数的函数?

Fra*_*ale 7 c++ templates member member-functions c++17

我有一个这样的功能:

void f(std::ofstream& ostrm)
{
    auto a = Myglobal->getData1();
    ostrm << a;

    auto b = Myglobal->getData2();
    ostrm << b;

    auto c = Myglobal->m_data1;
    ostrm << c;

    auto d = Myglobal->m_data2;
    ostrm << d;

    //...
    auto z = Myglobal->getData1000();
    ostrm << z;
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以创建将成员函数成员分解为代码的函数作为参数?

abc,D和z不同类型的)

lub*_*bgr 7

就在这里。一种方法是void f变成函数模板,然后将指针传递给所需数据成员或成员函数的成员,然后让std::invoke(C ++ 17,<functional>标头)完成其余工作:

template <class PtrToMember>
void f(std::ofstream &ostrm, PtrToMember m){
    ostrm << std::invoke(m, Myglobal);
}

// call like this:

f(someStream, &T::getData1);
f(someStream, &T::m_data1);
Run Code Online (Sandbox Code Playgroud)

当然,您应该用课程T类型代替Myglobal。有趣的std::invoke是它会自动处理所有成员(数据或函数)。

  • @ Jarod42好吧...公平点:)`f(someStream,&T :: getData1); f(someStream,&T :: m_data1);是57个字符,因此someStream &lt;&lt; Myglobal-&gt; getData1()&lt;&lt; Myglobal-&gt; m_data1;也是如此。至少此解决方案不需要更多的输入。但是现在当你想在`&lt;&lt;`之前将`std :: format`放入流中时... (2认同)

JeJ*_*eJo 6

@lubgr 解释使用std::invoke。一步可以整个代码行减少到一行,使用倍的表达

template<typename... Mems>
void f(std::ofstream& ostrm, Mems&&... args)
{
    ((ostrm << std::invoke(args, Myglobal) << " "), ...);
}
Run Code Online (Sandbox Code Playgroud)

并且您将一次将所需的成员或成员函数传递给该函数,而不是多次调用。

f(obj,
    &MyClass::m_data1, &MyClass::m_data2, &MyClass::m_data3,
    &MyClass::getData1, &MyClass::getData2, &MyClass::getData3);
Run Code Online (Sandbox Code Playgroud)

请参见现场示例


并且在函数中f为提供了另一个模板参数(用于Class),您可以使其成为完全通用的代码,而无需全局变量。

template<typename Class, typename... Mems>
void f(std::ofstream& ostrm, const Class& obj, Mems&&... args)
//                           ^^^^^^^^^^^^^^^^
{
    ((ostrm << std::invoke(args, obj) << " "), ...);
}
Run Code Online (Sandbox Code Playgroud)

现在在 main()

std::ofstream ostrm{"test_file.txt"};
const auto obj{ std::make_unique<MyClass>() };
f(ostrm,
    obj,
    &MyClass::m_data1, &MyClass::m_data2, &MyClass::m_data3,
    &MyClass::getData1, &MyClass::getData2, &MyClass::getData3);
Run Code Online (Sandbox Code Playgroud)

  • 这太棒了!但是,人们可能只会争论可读性。只要在指向会员国的地方购买一次,可读性就不一定是最终的目标。 (2认同)