如何编写一个不断敲击输出的包装器?
Posted
技术标签:
【中文标题】如何编写一个不断敲击输出的包装器?【英文标题】:How to write a wrapper that keeps rapping the output? 【发布时间】:2016-11-01 04:00:08 【问题描述】:基本上,我想做的是在某个抽象类上使用一个包装器,然后让相同的包装器类包装该类的任何成员函数的输出。继续这样做,以便始终包装所有对象。
喜欢(预编码)
wrap<set(1..10)> (multiply,2)
(divide,3)
(plus,5)
(inverse)
(collect first 10)
.unwrap()
除了最后一行之外的所有行都输出了一些东西。现在似乎意义不大,但我相信我们可以在上面应用一些有趣的东西,比如:
wrap<someClass> dat;
dat.splitIntoThreads(2)
(thingA) .clone()
(thingB) (thing1)
(thingC) (thing2)
(thingD) (thing3)
.nothing() (thing4)
.sync() .exit()
.addMerge()
这是我的换行代码:
template<class T>
struct wrap
wrap()
wrap(T b)a=b;
template<class L,class...R>
L operator() (L(T::*f)(R...),R...r)
return a.f(r...);
T a;
;
int main()
wrap<testClass> a;
a(&testClass::f,13,'a');
它正在工作(gcc,c++0x)。但是当我用以下内容替换第 6,7 行时(实际包装结果)
wrap<L> operator() (L(T::*f)(R...),R...r)
return wrap<L>(a.f(r...));
编译器只是说:创建指向非类类型“int”的成员函数的指针。
我该如何解决这个问题?有没有更好的办法呢?继承是一种方式,但由于我们可能在一个包装中包含变量实例,我认为它没有用。
编辑
这是我的测试课
struct testClass
int f(int a,char b)
return a+b;
;
我使用 wrap L 而不是 wrap T 的原因是返回类型可能并不总是 T。
【问题讨论】:
你不需要 a.*f 而不是 a.f 吗? @JerryJeremiah 我记得函数指针将被视为函数,并且工作代码中的 a.f 有效 您的testclass
定义如何?你能给我们一个sn-p吗?我试图模仿你的包装。 cpp.sh/8at6z 这似乎有效。我认为错误是您对testclass
的定义。 return wrap<L>(a.f(r...));
对我来说完全没问题。
问题是你想创建wrap<fundamental type>
ex。 wrap<int>
因为不能有指向 int
方法的指针。 T::*f
将扩展为 int::*f
或编译器这样认为 ;)。
【参考方案1】:
你可以试试这样的:
#include <iostream>
#include <type_traits>
template<class T, bool = false>
struct wrap
template <typename... Args>
wrap(Args&&... args) : astd::forward<Args>(args)... ;
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(T::*f)(R...),R...r)
return wrap<L,std::is_fundamental<L>::value > (a.*f)(r...);
T a;
;
template<class T>
struct wrap <T,true>
template <typename... Args>
wrap(Args&&... args) : astd::forward<Args>(args)...
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(*f)(T a, R...), R...r)
return wrap<L,std::is_fundamental<L>::value > f(a, r...);
T a;
;
class testClass
int m;
public:
testClass(int _m) : m_m
int multiAdd(int x, char y)
m += x + y;
return m;
;
int add(int a, char b)
return a+b;
int main()
wrap<testClass> a0;
std::cout << a(&testClass::multiAdd,0,'d')(add,'a').a<<std::endl;
wrap<int, true> b3;
std::cout << b(add,'a').a<<std::endl;
cpp.sh/6icg
【讨论】:
【参考方案2】:您的testclass
定义中似乎存在错误。请检查以下示例。
另外,operator() 中的wrap 可以作为参考返回。我认为没有必要创建用于 () 链接的临时对象。
template<class T>
struct wrap
template <typename... Args>
wrap(Args&&... args) : astd::forward<Args>(args)... ;
template<class L, class...R>
wrap<T>& operator() (L(T::*f)(R...),R...r)
a.f(r...);
return *this; //returning reference to current wrap object.
T a;
;
一个积累数字的测试类。
class testClass
int m;
public:
testClass(int _m) : m_m
int f(int x)
m += x;
std::cout << ' ' << m;
return m;
;
一个用法示例:
int main()
wrap<testClass> a0;
a(&testClass::f,13)(&testClass::f, 11)(&testClass::f,3)(&testClass::f, 21);
每一步累加的输出:
13 24 27 48
【讨论】:
您可能错误地认为结果类型与基类具有相同的类型。 @Logman 不。你能澄清一下你的意思吗?然后operato()
返回一个wrap<T>&
,这样我们就可以在返回类型上再次调用operator()
。
testClass::f 返回 int,这意味着他想像这样包装结果 wrap以上是关于如何编写一个不断敲击输出的包装器?的主要内容,如果未能解决你的问题,请参考以下文章
编写一个包装器将现有的 REST API 公开为 SOAP Web 服务?