如何在 class space 中为成员函数起别名?
How do I alias a member function in class space?
我希望能够从 class.
的对象中通过多个名称调用同一个成员函数
例如:
#include <string>
#include <stdio.h>
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
const auto& output = print; // attempting to alias. does not work
private:
std::string log;
};
int main()
{
Log log("LOG: Log started.");
log.print();
log.output(); // both should call the same function.
return 0;
}
此代码对我产生此错误 (gcc 7.3.0)
main.cpp:15:15: error: non-static data member declared with placeholder ‘const auto’
const auto& output = print; // attempting to alias. does not work
^~~~
main.cpp: In function ‘int main()’:
main.cpp:25:13: error: ‘class Log’ has no member named ‘output’
log.output(); // both should call the same function.
如何为函数名称定义别名?
据我所知,该语言不提供为成员函数定义别名的机制。
但是,如果您愿意使用调用成员函数的非成员函数,则可以定义别名。
#include <string>
#include <stdio.h>
namespace MyApp
{
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
private:
std::string log;
};
void print(Log const& log)
{
log.print();
}
auto& output = print; // OK
auto& write = print; // OK
}
int main()
{
MyApp::Log log("LOG: Log started.");
MyApp::print(log); // Works OK
MyApp::output(log); // Works OK
MyApp::write(log); // Works OK
return 0;
}
我会使用带有完美转发的可变参数模板
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
template<typename... Ts>
auto output(Ts&&... ts) const -> decltype(print(std::forward<Ts>(ts)...))
{
return print(std::forward<Ts>(ts)...);
}
private:
std::string log;
};
如果 print
的签名发生变化,则无需更改 output
中的任何内容(除了 const
ness 之外,必须进行相应更改)。唯一的问题是 output
签名的冗长和 call 的重复以在尾部 return 类型中打印(这在 C++14 中是不必要的)。好处是,即使添加了 print
的另一个重载,它也能正常工作!另一个 issue 将在 IDE 中,不会 转发 文档评论。
另一种选择是引入引用该函数的成员变量。
可以,您提供的代码中的问题是非静态成员变量上的auto
。
这里有一些关于如何做到这一点的例子,但是调用成员一点也不漂亮。如果这是访问 API 的用户,我个人会选择包装打印。
class Log {
public:
Log(std::string str)
: log(str) {
}
void print() const {
puts(log.c_str());
}
// Using auto.
static constexpr auto output = &print;
// Using function pointer.
using print_ptr_t = void (Log::*)() const;
print_ptr_t output2 = &Log::print;
private:
std::string log;
};
Log l{ "test log" };
(l.*l.output)();
(l.*l.output2)();
我希望能够从 class.
的对象中通过多个名称调用同一个成员函数例如:
#include <string>
#include <stdio.h>
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
const auto& output = print; // attempting to alias. does not work
private:
std::string log;
};
int main()
{
Log log("LOG: Log started.");
log.print();
log.output(); // both should call the same function.
return 0;
}
此代码对我产生此错误 (gcc 7.3.0)
main.cpp:15:15: error: non-static data member declared with placeholder ‘const auto’
const auto& output = print; // attempting to alias. does not work
^~~~
main.cpp: In function ‘int main()’:
main.cpp:25:13: error: ‘class Log’ has no member named ‘output’
log.output(); // both should call the same function.
如何为函数名称定义别名?
据我所知,该语言不提供为成员函数定义别名的机制。
但是,如果您愿意使用调用成员函数的非成员函数,则可以定义别名。
#include <string>
#include <stdio.h>
namespace MyApp
{
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
private:
std::string log;
};
void print(Log const& log)
{
log.print();
}
auto& output = print; // OK
auto& write = print; // OK
}
int main()
{
MyApp::Log log("LOG: Log started.");
MyApp::print(log); // Works OK
MyApp::output(log); // Works OK
MyApp::write(log); // Works OK
return 0;
}
我会使用带有完美转发的可变参数模板
class Log
{
public:
Log(std::string str)
: log(str)
{}
void print() const
{
puts(log.c_str());
}
template<typename... Ts>
auto output(Ts&&... ts) const -> decltype(print(std::forward<Ts>(ts)...))
{
return print(std::forward<Ts>(ts)...);
}
private:
std::string log;
};
如果 print
的签名发生变化,则无需更改 output
中的任何内容(除了 const
ness 之外,必须进行相应更改)。唯一的问题是 output
签名的冗长和 call 的重复以在尾部 return 类型中打印(这在 C++14 中是不必要的)。好处是,即使添加了 print
的另一个重载,它也能正常工作!另一个 issue 将在 IDE 中,不会 转发 文档评论。
另一种选择是引入引用该函数的成员变量。
可以,您提供的代码中的问题是非静态成员变量上的auto
。
这里有一些关于如何做到这一点的例子,但是调用成员一点也不漂亮。如果这是访问 API 的用户,我个人会选择包装打印。
class Log {
public:
Log(std::string str)
: log(str) {
}
void print() const {
puts(log.c_str());
}
// Using auto.
static constexpr auto output = &print;
// Using function pointer.
using print_ptr_t = void (Log::*)() const;
print_ptr_t output2 = &Log::print;
private:
std::string log;
};
Log l{ "test log" };
(l.*l.output)();
(l.*l.output2)();