有什么方法可以创建一个函数,该函数将成员函数或成员作为参数?
Is there any way to create a function that takes as argument a member function or a member?
我有这样的功能:
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;
}
有什么方法可以创建一个函数,该函数将 成员函数 或 成员 作为参数来分解此代码?
(a
,b
,c
,d和z
不是同一类型)
是的,有。一种方法是将 void f
变成函数模板,然后将指针传递给所需数据成员或成员函数的成员,让 std::invoke
(C++17, <functional>
header) 做其余:
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);
当然,您应该将 T
替换为 Myglobal
的类型。 std::invoke
的好处是它会自动处理所有成员(数据或函数)。
has explained the use of std::invoke
. One step further you can reduce the entire lines of code to a single line, using fold expression from c++17.
template<typename... Mems>
void f(std::ofstream& ostrm, Mems&&... args)
{
((ostrm << std::invoke(args, Myglobal) << " "), ...);
}
并且您将一次性将所需的成员或成员函数传递给函数,而不是多次调用。
f(obj,
&MyClass::m_data1, &MyClass::m_data2, &MyClass::m_data3,
&MyClass::getData1, &MyClass::getData2, &MyClass::getData3);
并且在函数f
中再提供一个模板参数(对于Class
),你可以使它成为完全通用的代码,不需要全局变量。
template<typename Class, typename... Mems>
void f(std::ofstream& ostrm, const Class& obj, Mems&&... args)
// ^^^^^^^^^^^^^^^^
{
((ostrm << std::invoke(args, obj) << " "), ...);
}
现在在 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);
我有这样的功能:
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;
}
有什么方法可以创建一个函数,该函数将 成员函数 或 成员 作为参数来分解此代码?
(a
,b
,c
,d和z
不是同一类型)
是的,有。一种方法是将 void f
变成函数模板,然后将指针传递给所需数据成员或成员函数的成员,让 std::invoke
(C++17, <functional>
header) 做其余:
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);
当然,您应该将 T
替换为 Myglobal
的类型。 std::invoke
的好处是它会自动处理所有成员(数据或函数)。
std::invoke
. One step further you can reduce the entire lines of code to a single line, using fold expression from c++17.
template<typename... Mems>
void f(std::ofstream& ostrm, Mems&&... args)
{
((ostrm << std::invoke(args, Myglobal) << " "), ...);
}
并且您将一次性将所需的成员或成员函数传递给函数,而不是多次调用。
f(obj,
&MyClass::m_data1, &MyClass::m_data2, &MyClass::m_data3,
&MyClass::getData1, &MyClass::getData2, &MyClass::getData3);
并且在函数f
中再提供一个模板参数(对于Class
),你可以使它成为完全通用的代码,不需要全局变量。
template<typename Class, typename... Mems>
void f(std::ofstream& ostrm, const Class& obj, Mems&&... args)
// ^^^^^^^^^^^^^^^^
{
((ostrm << std::invoke(args, obj) << " "), ...);
}
现在在 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);