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

基于父类纯虚方法的自动方法生成方案技术问询

Solution for Boilerplate Forwarding in RAII Wrappers for Factory Interfaces

Great question! Dealing with boilerplate forwarding code when wrapping a factory-generated interface is super annoying—let’s break down a clean, maintainable solution using macros + templates that eliminates manual repetition, while keeping RAII intact.

First, Let's Define the Problem Context

Let’s start with a concrete example of the factory interface you’re working with:

#include <memory>
#include <string>

// The library's factory interface (as described)
class FactoryInterface {
public:
    virtual ~FactoryInterface() = default;
    
    // Pure virtual methods we need to forward
    virtual void methodA() = 0;
    virtual int methodB(int param) = 0;
    virtual bool methodC(const std::string& str) const = 0;
    virtual void methodD() noexcept = 0;

    // Factory method returns concrete implementation
    static std::unique_ptr<FactoryInterface> create();
};

Without a helper approach, your wrapper would require writing tedious forwarding code for every pure virtual method—exactly what you’re trying to avoid.

The Solution: Macro + Template Forwarding

The key idea is to centralize the list of interface methods in a macro, then reuse that macro to generate both the interface declarations and the wrapper’s forwarding logic. This way, you only update the macro when the interface changes, not every forwarding method.

Step 1: Define a Method List Macro

First, create a macro that lists all the pure virtual methods from the interface, including return types, qualifiers (like const or noexcept), names, and parameters:

// Centralized list of interface methods - update this once when the interface changes
#define FACTORY_INTERFACE_METHODS \
    METHOD(void, , methodA) \
    METHOD(int, , methodB, int) \
    METHOD(bool, const, methodC, const std::string&) \
    METHOD(void, noexcept, methodD)

Step 2: Refactor the Interface (If Possible)

If you have control over the original library interface (or can wrap it in a header), use the macro to generate the pure virtual method declarations:

class FactoryInterface {
public:
    virtual ~FactoryInterface() = default;

    // Generate pure virtual method declarations
    #define METHOD(ret, qualifiers, name, ...) \
        virtual ret name(__VA_ARGS__) qualifiers = 0;
    FACTORY_INTERFACE_METHODS
    #undef METHOD

    static std::unique_ptr<FactoryInterface> create();
};

If you can’t modify the original interface, skip this step—you’ll still use the macro for your wrapper’s forwarding logic, just ensure the macro exactly matches the interface’s method signatures.

Step 3: Create a Reusable Forwarding Base Class

Build a template base class that uses the macro to generate all forwarding methods automatically. This class handles holding the implementation pointer and RAII via std::unique_ptr:

template <typename ImplType>
class ForwardingWrapperBase : public FactoryInterface {
protected:
    std::unique_ptr<ImplType> impl_;

public:
    explicit ForwardingWrapperBase(std::unique_ptr<ImplType> impl)
        : impl_(std::move(impl)) {}

    // Generate forwarding methods for all interface methods
    #define METHOD(ret, qualifiers, name, ...) \
        ret name(__VA_ARGS__) qualifiers override { \
            return impl_->name(__VA_ARGS__); \
        }
    FACTORY_INTERFACE_METHODS
    #undef METHOD
};

Step 4: Build Your Custom Wrapper

Now your custom wrapper inherits from the forwarding base, adds your new methods, and leverages RAII automatically (thanks to std::unique_ptr handling destruction):

class MyCustomWrapper : public ForwardingWrapperBase<FactoryInterface> {
public:
    MyCustomWrapper()
        : ForwardingWrapperBase(FactoryInterface::create()) {}

    // Add your custom methods here
    void customWorkflow() {
        // Example: Combine existing interface methods with custom logic
        std::cout << "Running custom pre-processing..." << std::endl;
        methodA();
        int result = methodB(42);
        std::cout << "Got result from methodB: " << result << std::endl;
    }

    // Optional: Override any interface method if needed
    void methodA() override {
        std::cout << "Wrapped methodA - adding custom behavior!" << std::endl;
        impl_->methodA();
    }
};

Why This Works

  • No Boilerplate: You only maintain the FACTORY_INTERFACE_METHODS macro—all forwarding code is generated automatically.
  • RAII Compliance: The std::unique_ptr in the base class ensures the implementation is destroyed when your wrapper goes out of scope, no manual cleanup needed.
  • Flexibility: Add custom methods or override existing ones without touching the forwarding logic.
  • Maintainability: When the original interface changes, you update the macro once instead of rewriting every forwarding method.

Key Notes

  • If the interface has methods with default parameters, adjust the macro to include them (e.g., METHOD(int, , methodE, int = 0)).
  • For methods with complex signatures (like pointers or references), ensure the macro matches exactly to avoid compilation errors.
  • If you don’t want your wrapper to inherit from FactoryInterface (e.g., to hide some methods), you can modify the base class to not inherit, and manually expose only the methods you need—but this brings back some boilerplate. For most cases, inheriting is the cleanest approach.

内容的提问来源于stack exchange,提问作者eugenioperez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:06:49