首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用函数/模板替换宏

用函数/模板替换宏
EN

Stack Overflow用户
提问于 2014-02-18 15:43:38
回答 3查看 2.3K关注 0票数 4

我想用函数/模板替换宏:

代码语言:javascript
复制
#define FOO( f ) \
    int result = m_Member.f; \
    switch ( result ) \
    { \
    case 1: \
        m_pMember1->f; \
        break;
    case 2:
        m_pMember2->f; \
        break;
    }

class foo
{
public:
    void foo1(int x, int y)
    {
        FOO( foo1(x, y) )
    }
    void foo2(int x, double y, void *z)
    {
        FOO( foo2(x, y) )
    }
protected:
    fooA m_Member;
    fooB m_Member1;
    fooC m_Member2;
};

因此,我的问题是函数名与参数一起传递给宏。我可以重写对FOO( foo1,x,y)的调用,然后处理变量参数列表。因此宏将只定义一个函数调用。但也许有一个更优雅的解决方案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-18 16:13:07

事实上,这是不可能的。

问题是,从本质上说,模板是类型安全的。然而,你的例子并非如此。名称foo2没有任何固有的约束它可以应用到的类型集!

为了说明这个问题,请考虑一个典型的成员函数:

代码语言:javascript
复制
struct Foo { int doit(double x, double y); };

它的类型是int (Foo::*)(double,double)

注意方法所属的类的名称如何出现在类型本身中。

因此,不能在两个无关的类上调用doit ..。所以我担心你会重复:

代码语言:javascript
复制
class foo {
public:
    void foo1(int x, int y)
    {
        dispatch(&fooA::foo1, &fooB::foo1, &fooC::foo1, x, y);
    }

    void foo2(int x, double y, void *z)
    {
        dispatch(&fooA::foo2, &fooB::foo2, &fooC::foo2, x, y, z);
    }

private:
    template <typename... Args>
    void dispatch(int (fooA::* f)(Args...),
                  void (fooB::* g)(Args...),
                  void (fooC::*h)(Args...),
                  Args... args)
    {
        switch((m_Member.*f)(args...)) {
        case 1: (m_Member1.*g)(args...); return;
        case 2: (m_Member2.*h)(args...); return;
        }
    }

    fooA m_Member;
    fooB m_Member1;
    fooC m_Member2;
};

没错,它起作用了

票数 3
EN

Stack Overflow用户

发布于 2014-02-18 15:58:10

如果您可以使用一些虚拟函数向fooBfooC (这里称为foo_base )添加一个基类,那么您可以使用以下代码来实现这一点:

代码语言:javascript
复制
class foo
{
private:
    template<typename... Ts>
    void another_foo(int (fooA::*f)(Ts...), void (foo_base::*g)(Ts...), Ts const... vals)
    {
        switch ((m_Member.*f)(vals...)) {
        case 1:
            (m_pMember1->*g)(vals...);
            break;

        case 2:
            (m_pMember2->*g)(vals...);
            break;
        }
    }

public:
    void foo1(int x, int y)
    {
        another_foo(&fooA::foo1, &foo_base::foo1, x, y);
    }

    void foo2(int x, double y, void *z)
    {
        another_foo(&fooA::foo2, &foo_base::foo2, x, y);
    }

protected:
    fooA m_Member;
    fooB m_Member1;
    fooC m_Member2;
};

虚拟函数可能会被去虚拟化,因为静态地知道m_pMember1m_pMember2的静态类型。

票数 0
EN

Stack Overflow用户

发布于 2014-02-18 16:51:20

以下可能有帮助:(http://ideone.com/5QIBZx)

代码语言:javascript
复制
#define Return(ret) decltype ret { return ret; }

struct foo1Caller
{
    template <typename T, typename... Args>
    auto operator () (T& t, Args... args) -> Return((t.foo1(args...)))
};

struct foo2Caller
{
    template <typename T, typename... Args>
    auto operator () (T& t, Args... args) -> Return((t.foo2(args...)))
};


class foo
{
public:
    void foo1(int x, int y)
    {
        dispatch(foo1Caller(), x, y);
    }
    void foo2(int x, double y, void *z)
    {
        dispatch(foo2Caller(), x, y, z);
    }

private:
    template <typename T, typename... Args>
    void dispatch(T caller, Args... args)
    {
        switch (caller(m_Member, args...)) {
            case 1: caller(m_Member1, args...); return;
            case 2: caller(m_Member2, args...); return;
        }
    }

    fooA m_Member;
    fooB m_Member1;
    fooC m_Member2;
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21858560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档