【问题标题】:Correct function signature template for member function更正成员函数的函数签名模板
【发布时间】:2015-04-26 06:46:56
【问题描述】:

跟进我最近提出的一个问题,其中可能有一些不必要的东西,但示例很小,我想做什么(当然,如果您能想到其他很酷的方法,请分享您的想法),是允许用户使用特定类型激活非虚拟非接口关联子方法(请让我们专注于如何而不是为什么:))。

我的最后一个错误涉及成员函数签名而不是实际选择,我不知道如何允许完美转发,我尝试了当前无法工作的解决方案(副本),我也尝试过转移Args_t&& 和转发,这也不起作用,关于如何正确传输成员函数的任何建议?我怀疑激活函数定义是错误的......

我已经添加了一个演示编译错误的代码,您也可以将 activate Args_t 输入参数更改为 Args_t&& 然后 forward(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;
}

【问题讨论】:

  • 这两个分支的区别在哪里? type == Type::One? activate&lt;B&gt;(&amp;B::func, parent) : activate&lt;B&gt;(&amp;B::func, parent)
  • 应该是里面的模板,没有注意到,因为它只是例如修改过的,谢谢。
  • delete a; 导致未定义的行为。在实践中,它通常会破坏堆。
  • 这只是一个示例代码,可以删除它............
  • A 没有虚拟析构函数,因此不会调用 a 指向的 B 实例的析构函数。形式上,这会导致未定义的行为,尽管我不同意在这种情况下它应该破坏堆。

标签: c++ templates variadic-templates member-functions


【解决方案1】:

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

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

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

【讨论】:

  • 既然TTT 应该是一样的(传递另一个类的成员函数有什么意义),为什么要使用两个不同的类型名?
  • @RedX 我认为在某些情况下它们会被推断为不同的类型。 T 将始终被推导出为非引用类型。这不适用于TT。当然,我可能错了。
  • 如果我在激活时替换了这两行,我得到错误:指向成员类型'NonCopyable& (B::)(NonCopyable&, bool)' 的指针与对象类型'A' 不兼容,你能把在我的例子中?它应该编译都一样
  • @Alon 已更新。希望能帮助到你。它确实需要一些努力。
  • @Alon 注意用法。你不需要像activate&lt;B&gt;那样指定派生类型,只需activate
猜你喜欢
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多