C ++ 11 как прокси функции класса, имеющего только свое имя и родительский класс?

Интересно, возможно ли с помощью boost :: mpl / preprocessor или некоторых других функций 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. Возможно ли и как создать такой класс, который бы передавал прокси любое количество функций перегрузки, не зная там типов (только имена)?

3

Решение

Как насчет этого:

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

Изменить (уменьшенная версия благодаря комментариям)

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)...));  \
}                                                              \
};
4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector