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

无需模板构建std::function包装类WrapperFunction的技术问询

Absolutely, this is totally doable! Let's walk through how to build your WrapperFunction class that decomposes and stores the core parts of a std::function—return type, arguments, and the callable itself—without requiring the wrapper to be a template class upfront.

Core Concept: Type Extraction + Type Erasure

First, we need two key pieces to make this work:

  1. A way to extract the return type and argument types from a given std::function (we'll use template specialization for this).
  2. A way to store any type of std::function in a non-template class (we'll use std::any for safe type erasure, available in C++17+).

Step 1: Function Traits for Type Extraction

We'll create a helper template to pull out the return type and argument types from a std::function:

#include <functional>
#include <tuple>
#include <typeinfo>
#include <any>

// Helper traits to extract type info from std::function
template<typename Func>
struct FunctionTraits;

// Specialization for std::function<R(Args...)>
template<typename R, typename... Args>
struct FunctionTraits<std::function<R(Args...)>> {
    using ReturnType = R;
    using ArgsTuple = std::tuple<Args...>;
    
    // Optional: Get individual argument types by index
    template<std::size_t N>
    using ArgType = std::tuple_element_t<N, ArgsTuple>;
};

Step 2: Implement the WrapperFunction Class

This class will accept any std::function in its constructor, store the callable, and record the return/argument type info. We'll add getter methods to retrieve all stored data:

class WrapperFunction {
public:
    // Constructor: Accept any std::function and store its components
    template<typename R, typename... Args>
    WrapperFunction(std::function<R(Args...)> func)
        : m_stored_func(std::move(func)),
          m_return_type(&typeid(R)),
          m_args_type(&typeid(typename FunctionTraits<decltype(func)>::ArgsTuple)) {}

    // Getter: Retrieve the stored callable (returns std::any for type erasure)
    const std::any& get_function() const {
        return m_stored_func;
    }

    // Getter: Get type info for the return type
    const std::type_info& get_return_type() const {
        return *m_return_type;
    }

    // Getter: Get type info for the arguments (as a tuple of argument types)
    const std::type_info& get_args_type() const {
        return *m_args_type;
    }

    // Helper: Safely cast the stored function back to its original std::function type
    // Throws std::bad_any_cast if the type doesn't match
    template<typename R, typename... Args>
    std::function<R(Args...)> get_as() const {
        return std::any_cast<std::function<R(Args...)>>(m_stored_func);
    }

private:
    std::any m_stored_func;               // Stores the callable (any std::function type)
    const std::type_info* m_return_type;  // Type info for the return value
    const std::type_info* m_args_type;    // Type info for the argument tuple
};

Step 3: Example Usage

Let's test the wrapper with different functions/lambdas to see it in action:

#include <iostream>
#include <string>

int main() {
    // Wrap a simple addition lambda
    auto add = [](int a, int b) { return a + b; };
    std::function<int(int, int)> add_func = add;
    WrapperFunction add_wrapper(add_func);

    // Check type info (note: type names are compiler-specific)
    std::cout << "Return type: " << add_wrapper.get_return_type().name() << "\n";
    std::cout << "Args type: " << add_wrapper.get_args_type().name() << "\n";

    // Retrieve and call the function
    auto retrieved_add = add_wrapper.get_as<int, int, int>();
    std::cout << "5 + 7 = " << retrieved_add(5, 7) << "\n\n";

    // Wrap a void-returning lambda
    auto greet = [](const std::string& name) {
        std::cout << "Hello, " << name << "!\n";
    };
    std::function<void(const std::string&)> greet_func = greet;
    WrapperFunction greet_wrapper(greet_func);

    auto retrieved_greet = greet_wrapper.get_as<void, const std::string&>();
    retrieved_greet("Alice");

    return 0;
}

Key Notes

  • C++ Version: std::any requires C++17 or later. If you're stuck on an older version, you can use a void* with a custom deleter and type checker, but std::any is far safer.
  • Type Safety: When using get_as(), you must specify the exact return type and argument types. Mismatched types will throw a std::bad_any_cast exception.
  • Type Info: The name() method of std::type_info returns a compiler-specific string (not human-readable in all cases), but you can use == to compare types for equality.
  • Extensibility: If you need more granular argument info (like number of arguments or individual argument types), you can extend the FunctionTraits to store that data in WrapperFunction.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:28:26