Reputation: 1282
I would like to be able to call the same member function by multiple names from an object of the class.
For example:
#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;
}
This code yields this error for me (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.
How can I define an alias for a function name?
Upvotes: 6
Views: 6668
Reputation: 3947
You can, the problem in your provided code is the auto
on a non-static member variable.
Here are some examples on how to do it, but calling the member is not pretty at all. If this is a user accessed API, I would personally go with wrapping print.
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)();
Upvotes: 1
Reputation: 5209
I would go with variadic template with perfect forwarding
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;
};
If signature of print
changes, there is no need to change anything in output
(apart from const
ness, that has to be changed accordingly). The only issue is verboseness of output
signature and duplication of call to print in trailing return type (which is unnecessary in C++14). The good thing is that it works even if another overload of print
is added! Another issue would be in IDE, which wouldn't forward documentation comments.
Another option would be to introduce member variables referencing the function.
Upvotes: 7
Reputation: 206697
As far as I know, the language does not provide a mechanism to define an alias for a member function.
However, if you are willing to use a non-member function that calls the member function, you have the ability to define an alias.
#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;
}
Upvotes: 4