成员函数的正确函数签名模板



根据我最近问的一个问题,其中可能有一些不必要的东西,但这个例子很小,我想做什么(当然,如果你能想出其他很酷的方法来做这件事,请分享你的想法),是允许用户使用特定类型激活非虚拟非接口关联子方法(请,让我们集中讨论如何激活,而不是为什么激活:)。

我的最后一个错误涉及成员函数签名,而不是选择。实际上,我不知道如何允许完美的转发,我尝试过目前永远无法工作的解决方案(副本),我也尝试过传输Args_t&并就如何正确转移成员职能提出了任何建议,但也没有奏效?我怀疑激活功能防御是错误的。。。

我添加了一段代码来演示编译错误,您还可以将activate Args_t输入参数更改为Args_t&然后转发(args)。。。去看第二个。。。

谢谢。

struct Type {
enum Value {
One,
Two
};
};
struct A {};
template<typename Type_t, typename R, typename... Args_t>
auto activate(R (Type_t::* f)(Args_t...), A& parent, Args_t... args) -> R // args&& won't comppile either..
{ return (static_cast<Type_t&>(parent).*f)(args...); }
template<typename Type_t, typename R, typename... Args_t>
auto activate(R (Type_t::* f)(Args_t...) const, A const& parent, Args_t... args) -> R
{ return (static_cast<Type_t const&>(parent).*f)(args...); }
struct NonCopyable { public: NonCopyable() {} private: NonCopyable(NonCopyable const& other) {} };
struct B : public A { NonCopyable& foo(NonCopyable& other, bool test) { return other; } };
struct C : public A { NonCopyable& foo(NonCopyable& other, bool test) { return other; } }; // does something else obviously...
#define FuncSelect0(type, parent, func) 
type == Type::One? activate<B>(&B::func, parent) :  
activate<C>(&C::func, parent)
#define FuncSelect1(type, parent, func, arg1) 
type == Type::One? activate<B>(&B::func, parent, arg1) :  
activate<C>(&C::func, parent, arg1)
#define FuncSelect2(type, parent, func, arg1, arg2) 
type == Type::One? activate<B>(&B::func, parent, arg1, arg2) :  
activate<C>(&C::func, parent, arg1, arg2)
#define GET_FS(_1,_2, _3, _4, _5, NAME,...) NAME
#define FuncSelect(...) (GET_FS(__VA_ARGS__, FuncSelect2, FuncSelect1, FuncSelect0)(__VA_ARGS__))
int main() {
NonCopyable n;
bool t;
A* a = new B;
NonCopyable& c = FuncSelect(Type::One, *a, foo, n, t);
delete a;
return 0;
}

不太确定,但这就是您想要的吗?

更新:有了这些重载,它应该是非常通用的。

#include <iostream>
#include <utility>
struct X {};
struct A: X {
int f(int a, int b) { return a + b; }
};
struct B: X {
int f(int a, int b) const { return a * b; }
};
template <typename D, typename B>
const D& forward_cast(const B& b) { return (const D&)b; }
template <typename D, typename B> 
D& forward_cast(B& b) { return (D&)b; }
template <typename D, typename B>
const D&& forward_cast(const B&& b) { return (const D&&)b; }
template <typename D, typename B> 
D&& forward_cast(B&& b) { return (D&&)b; }
// I see no need to use the trailing return type syntax
template <typename T, typename TT, typename R, typename... Args, typename... Argss> inline
R activate(R (T::*pfn)(Args...), TT&& obj, Argss&&... args) {
return (forward_cast<T>(std::forward<TT>(obj)).*pfn)(std::forward<Argss>(args)...);
}
template <typename T, typename TT, typename R, typename... Args, typename... Argss> inline
R activate(R (T::*pfn)(Args...) const, TT&& obj, Argss&&... args) {
return (forward_cast<T>(std::forward<TT>(obj)).*pfn)(std::forward<Argss>(args)...);
}
int main() {
A a;
B b;
X* p = &a;
std::cout << activate(&A::f, *p, 1, 2) << 'n';
p = &b;
std::cout << activate(&B::f, *p, 1, 2) << 'n';
}

最新更新