You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++如何单语句声明成员函数指针?或生成调用B成员的宏?

问题与解答

原代码背景

以下是用于衔接通用算法与外部生成类(以B为例)的代码:

// 外部生成的类
struct B {
    void foo(int);
    void foo();

    int bar();
    int bar() const;

    float blah(int) const;
};

#define DECLARE_METHOD_TYPE(TName, CName, Func)    \
     template<typename ...Args>                    \
     using TName = decltype(                       \
     std::declval<CName>().Func(std::declval<Args>() ...)) \
         (CName::*) (Args...)

#define METHOD_PTR(TName, ... ) static constexpr TName<__VA_ARGS__>

// 桥接类
struct A 
{
    DECLARE_METHOD_TYPE(FooPtr, B, foo);

    // 需要分别声明两种版本
    DECLARE_METHOD_TYPE(BarPtr, B, bar);
    DECLARE_METHOD_TYPE(BarPtrConst, B, bar) const;

    // 必须是const版本
    DECLARE_METHOD_TYPE(BlahPtrConst, B, blah) const;

    METHOD_PTR(FooPtr, int) b_foo_n = &B::foo;
    METHOD_PTR(FooPtr)      b_foo   = &B::foo;

    METHOD_PTR(BarPtr)      b_bar   = &B::bar;
    METHOD_PTR(BarPtrConst) b_cbar  = &B::bar;

    // 必须严格匹配参数
    METHOD_PTR(BlahPtrConst, int) b_blah = &B::blah;
};

核心问题

  • 当前实现中每个成员函数指针需要先声明类型再定义指针,能否用单语句完成每个指针的声明?核心难点在于指针类型是模板,需要唯一类型名。
  • 能否创建宏来生成调用B类成员的成员函数(类似访问者模式)?目前可以声明这类函数,但无法完成定义。

解答

1. 单语句完成成员函数指针声明

可以通过合并宏逻辑,直接在定义指针的同时推导并生成类型,不需要单独的DECLARE_METHOD_TYPE步骤。核心思路是利用decltype推导成员函数的类型,结合宏的命名隔离技巧:

#include <utility>

// 外部生成的类
struct B {
    void foo(int);
    void foo();

    int bar();
    int bar() const;

    float blah(int) const;
};

// 合并类型声明与指针定义的宏(非const成员)
#define DEFINE_METHOD_PTR(VarName, CName, Func, ...) \
    template<typename... Args> \
    using _##VarName##_type = decltype(std::declval<CName>().Func(std::declval<Args>()...)) (CName::*)(Args...); \
    static constexpr _##VarName##_type<__VA_ARGS__> VarName = &CName::Func;

// 处理const成员函数的版本
#define DEFINE_CONST_METHOD_PTR(VarName, CName, Func, ...) \
    template<typename... Args> \
    using _##VarName##_type = decltype(std::declval<const CName>().Func(std::declval<Args>()...)) (const CName::*)(Args...); \
    static constexpr _##VarName##_type<__VA_ARGS__> VarName = &CName::Func;

// 桥接类
struct A 
{
    // 非const成员函数,带参数
    DEFINE_METHOD_PTR(b_foo_n, B, foo, int)
    // 非const成员函数,无参数
    DEFINE_METHOD_PTR(b_foo, B, foo)

    // 非const版bar
    DEFINE_METHOD_PTR(b_bar, B, bar)
    // const版bar
    DEFINE_CONST_METHOD_PTR(b_cbar, B, bar)

    // const版blah,带参数
    DEFINE_CONST_METHOD_PTR(b_blah, B, blah, int)
};

这里通过下划线前缀的模板别名(_##VarName##_type)避免命名冲突,在宏内部隐式完成类型声明,最终实现单语句完成指针的声明与定义。

2. 宏生成调用B类成员的访问者函数

可以创建宏自动生成A中调用B成员的函数,需要处理返回值、参数列表、const修饰符三种核心情况。假设A持有B的指针或引用(如B* b;),宏设计如下:

手动指定返回值版本

#include <utility>

// 外部生成的类
struct B {
    void foo(int);
    void foo();

    int bar();
    int bar() const;

    float blah(int) const;
};

// 生成非const访问函数
#define GENERATE_VISITOR_FUNC(RetType, FuncName, ...) \
    RetType FuncName(__VA_ARGS__) { \
        return b->FuncName(__VA_ARGS__); \
    }

// 生成const访问函数
#define GENERATE_CONST_VISITOR_FUNC(RetType, FuncName, ...) \
    RetType FuncName(__VA_ARGS__) const { \
        return b->FuncName(__VA_ARGS__); \
    }

// 桥接类
struct A 
{
    B* b; // 持有B的指针

    // 生成foo的两个版本
    GENERATE_VISITOR_FUNC(void, foo, int x)
    GENERATE_VISITOR_FUNC(void, foo)

    // 生成bar的非const版本
    GENERATE_VISITOR_FUNC(int, bar)
    // 生成bar的const版本
    GENERATE_CONST_VISITOR_FUNC(int, bar)

    // 生成blah的const版本
    GENERATE_CONST_VISITOR_FUNC(float, blah, int x)
};

自动推导返回值版本(C++14及以上)

如果不想手动指定返回值,可结合auto返回值推导进一步简化:

// 自动推导返回值的非const访问宏
#define GENERATE_AUTO_VISITOR_FUNC(FuncName, ...) \
    auto FuncName(__VA_ARGS__) { \
        return b->FuncName(__VA_ARGS__); \
    }

// 自动推导返回值的const访问宏
#define GENERATE_AUTO_CONST_VISITOR_FUNC(FuncName, ...) \
    auto FuncName(__VA_ARGS__) const { \
        return b->FuncName(__VA_ARGS__); \
    }

struct A 
{
    B* b;

    GENERATE_AUTO_VISITOR_FUNC(foo, int x)
    GENERATE_AUTO_VISITOR_FUNC(foo)
    GENERATE_AUTO_VISITOR_FUNC(bar)
    GENERATE_AUTO_CONST_VISITOR_FUNC(bar)
    GENERATE_AUTO_CONST_VISITOR_FUNC(blah, int x)
};

这种方式无需手动匹配返回值,宏会自动适配B类成员函数的签名。


内容的提问来源于stack exchange,提问作者Swift - Friday Pie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:17:45