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

编写C++ Adapter类:适配函数对象/指针的返回值类型包装器

Alright, let's build this Adapter class you're asking for. The key idea is to wrap any callable (function pointers, functors, lambdas) into a type that always returns your predefined ReturnType, no matter what the wrapped callable's signature is.

Creating the Adapter Class in C++

Core Requirements Recap

You want a class named Adapter that:

  • Takes any callable (function pointer, functor, lambda) in its constructor
  • Stores the callable by value (using std::function works perfectly here)
  • Acts as a functor itself, wrapping the internal callable
  • Enforces a fixed return type (ReturnType) regardless of the wrapped callable's return type or parameter list

Implementation

First, let's write the code. This implementation uses C++20 features for simplicity (we'll cover compatibility notes later):

#include <functional>
#include <utility>
#include <type_traits>

// Predefine your ReturnType, or make it a template parameter for flexibility
using ReturnType = int;

template <typename Ret = ReturnType>
class Adapter {
public:
    // Constructor: Accept any callable and wrap it to enforce Ret return type
    template <typename Callable>
    Adapter(Callable&& callable, Ret default_void_ret = {})
        : m_wrapped_func([callable = std::forward<Callable>(callable), default_void_ret](auto&&... args) -> Ret {
            // Handle void return types from the wrapped callable
            if constexpr (std::is_void_v<std::invoke_result_t<decltype(callable), decltype(args)...>>) {
                std::invoke(callable, std::forward<decltype(args)>(args)...);
                return default_void_ret;
            } else {
                // Convert the callable's return value to Ret
                return static_cast<Ret>(std::invoke(callable, std::forward<decltype(args)>(args)...));
            }
        }) {}

    // Make Adapter act as a functor: forward args to wrapped callable, return Ret
    template <typename... Args>
    Ret operator()(Args&&... args) const {
        return m_wrapped_func(std::forward<Args>(args)...);
    }

private:
    // Generic std::function to accept any parameter list (C++20+)
    std::function<Ret(auto&&...)> m_wrapped_func;
};

How It Works

Let's break down the key parts:

  • Constructor: The template constructor accepts any callable. We wrap it in a lambda that handles two cases:
    • If the wrapped callable returns void, we execute it and return a default value for Ret (you can customize this default via the constructor's second parameter).
    • For non-void return types, we cast the result to Ret (adjust this cast if you need more complex conversion logic).
  • operator(): The templated operator accepts any number/type of arguments, forwards them to the wrapped function, and returns the enforced Ret type.
  • std::function<Ret(auto&&...)>: This C++20 feature lets us store a callable that accepts any parameter list, which is perfect for handling the varied signatures of your input callables.

Example Usage

Let's test this with different callables to see it in action:

#include <iostream>
#include <string>

// Test 1: Regular function returning double
double add(double a, double b) { return a + b; }

// Test 2: Lambda returning void
void print_greeting(const std::string& name) { std::cout << "Hello, " << name << "!\n"; }

// Test 3: Functor returning bool
struct PositiveChecker {
    bool operator()(int num) { return num > 0; }
};

int main() {
    // Wrap the add function: converts double return to int
    Adapter<int> adapter_add(add);
    std::cout << adapter_add(2.7, 3.3) << "\n"; // Output: 6

    // Wrap the print_greeting lambda: returns default int (0) after execution
    Adapter<int> adapter_greet([](const std::string& n) { print_greeting(n); });
    std::cout << adapter_greet("Kirill") << "\n"; // Output: Hello, Kirill! followed by 0

    // Wrap the functor: converts bool to int (true -> 1, false -> 0)
    Adapter<int> adapter_check(PositiveChecker{});
    std::cout << adapter_check(-42) << "\n"; // Output: 0

    // Wrap a no-argument function
    Adapter<int> adapter_fixed([]() { return 100; });
    std::cout << adapter_fixed() << "\n"; // Output: 100

    return 0;
}

Compatibility Notes

  • If you're stuck on C++17 (no support for std::function with auto parameters), you can replace the std::function storage with a templated member, but that makes the Adapter type dependent on the wrapped callable's type. Alternatively, use type erasure manually, but it's more verbose.
  • If your ReturnType doesn't have a default constructor, make sure to pass a valid default value to the Adapter constructor for void-returning callables.
  • Adjust the static_cast to a custom conversion function if you need more control over how the wrapped callable's return value is converted to ReturnType.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:54:33