【问题标题】:C++11 how to proxy class function having only its name and parent class?C ++ 11如何代理只有其名称和父类的类函数?
【发布时间】:2012-11-27 20:04:58
【问题描述】:

我想知道是否可以使用 boost::mpl/preprocessor 或一些 noce C++11 特性从类类型和函数名创建函数代理。

假设我们有:

  inline void set_email(const ::std::string& value);
  inline void set_email(const char* value);

课内电子邮件。我们知道它有 set_email 函数,我们想创建一个类似 API 的代理类

PROXY(Email, set_email, MyEmail)

Email * email = new Email();
MyEmail * myEmail = new MyEmail(email);

并且能够调用任何 set_email 重载。是否有可能以及如何创建这样的类来代理不知道类型(仅名称)的任意数量的重载函数?

【问题讨论】:

  • 对于可变参数模板和完美转发来说,这似乎是一项完美的工作,尽管这种需求值得怀疑。
  • 请注意,Xeo 不仅仅是在炫耀自己的言辞——关键字确实是“可变参数模板”和“完美转发”——这都是 C++11 的特性。

标签: c++ boost c++11 boost-mpl boost-preprocessor


【解决方案1】:

这个怎么样:

proxy_macro.hpp

#include <type_traits>
#include <utility>

#define PROXY(proxified, member_function, proxy_name)                                                                           \
  class proxy_name                                                                                                              \
  {                                                                                                                             \
  private:                                                                                                                      \
    proxified & ref_;                                                                                                           \
                                                                                                                                \
  public:                                                                                                                       \
    proxy_name(proxified &ref)                                                                                                  \
      : ref_(ref)                                                                                                               \
      {                                                                                                                         \
      }                                                                                                                         \
                                                                                                                                \
    /* general version */                                                                                                       \
    template<typename ... Args>                                                                                                 \
    auto member_function(Args&& ... args)                                                                                       \
    -> typename std::enable_if<!std::is_void<decltype(ref_.member_function(std::forward<Args>(args)...))>::value,               \
                               decltype(ref_.member_function(std::forward<Args>(args)...))>::type                               \
      {                                                                                                                         \
        return (ref_.member_function(std::forward<Args>(args)...));                                                             \
      }                                                                                                                         \
                                                                                                                                \
    /* void return type version */                                                                                              \
    template<typename ... Args>                                                                                                 \
    auto member_function(Args&& ... args)                                                                                       \
    -> typename std::enable_if<std::is_void<decltype(ref_.member_function(std::forward<Args>(args)...))>::value,                \
                               void>::type                                                                                      \
      {                                                                                                                         \
        ref_.member_function(std::forward<Args>(args)...);                                                                      \
      }                                                                                                                         \
                                                                                                                                \
  };

这对我在g++ 4.7 上编译和工作正常:

#include "proxy_macro.hpp"

#include <iostream>
#include <string>

class   Email
{
public:  
  void set_email(const ::std::string& value)
  {
    std::cout << value << std::endl;
  }

  void set_email(const char* value)
  {
    std::cout << value << std::endl;
  }

  int   set_email()
  {
    return (42);
  }

};

PROXY(Email, set_email, MyEmail)

int main(void)
{
  Email   mail;
  MyEmail my_mail(mail);

  std::string str = "test string";
  const char * ptr = "test char pointer";

  my_mail.set_email(str);
  my_mail.set_email(ptr);

  std::cout << "test return: " << my_mail.set_email() << std::endl;

  return (0);
}

编辑(感谢 cmets 的小版本)

proxy_macro.hpp

#include <type_traits>
#include <utility>

#define PROXY(proxified, member_function, proxy_name)                \
  class proxy_name                                                   \
  {                                                                  \
  private:                                                           \
    proxified & ref_;                                                \
                                                                     \
  public:                                                            \
    proxy_name(proxified &ref)                                       \
      : ref_(ref)                                                    \
      {                                                              \
      }                                                              \
                                                                     \
    template<typename ... Args>                                      \
    auto member_function(Args&& ... args)                            \
    -> decltype(ref_.member_function(std::forward<Args>(args)...))   \
      {                                                              \
        return (ref_.member_function(std::forward<Args>(args)...));  \
      }                                                              \
  };

【讨论】:

  • Yes it works... 我现在唯一想知道的是如何以自动方式获取所有类函数(包括继承的)的列表?
  • @myWallJSON 我不知道这样做的“足够好”的方式。我见过的最好的想法之一是使用boost::fusion 的宏,例如BOOST_FUSION_ADAPT_STRUCT,还有this question and the provided answers 可能会引导你找到有用的东西。
  • void 函数返回void 是合法的,所以我认为不需要特殊情况。 void foo() {}; void bar() { return foo(); } 有效(完全支持您编写的代码类型)。
  • @LucTouraille 我不知道,谢谢!我用较小的版本编辑了答案。
  • 使用Args&amp;&amp;... std::forward... 是否存在运行时损失,或者所有这些都是在编译时完成的?
猜你喜欢
  • 2015-12-18
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
相关资源
最近更新 更多