如何在类空间中为成员函数添加别名?

时间:2018-07-30 21:43:34

标签: c++ function class alias member-functions

我希望能够通过该类对象的多个名称调用同一成员函数。

例如:

#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.

如何为函数名称定义别名?

3 个答案:

答案 0 :(得分:4)

据我所知,该语言没有提供为成员函数定义别名的机制。

但是,如果您愿意使用调用成员函数的非成员函数,则可以定义别名。

#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;
}

答案 1 :(得分:3)

我会选择具有完美转发功能的可变参数模板

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之外,还必须进行相应的更改)。唯一的问题是output签名的冗长性和 call 的重复以尾随返回类型进行打印(在C ++ 14中是不必要的)。好消息是,即使添加了print的另一个重载,它也可以工作!另一个问题将在IDE中,而不会转发文档注释。

另一种选择是引入引用该函数的成员变量。

答案 2 :(得分:0)

您可以,您提供的代码中的问题是非静态成员变量上的 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)();