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

C++11下无dynamic_cast实现异构函数顺序执行容器是否可行?

可以实现!这里有一个基于C++11的方案

完全可以在C++11中实现你的需求,不需要依赖dynamic_cast,核心思路是用类型擦除技术来统一不同函数的存储和调用接口。下面是具体的实现步骤和代码示例:

1. 先实现一个简易的类型擦除容器(替代C++17的std::any)

因为C++11没有标准的std::any,我们需要自己写一个轻量版本来持有任意类型的值:

#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include <typeindex>
#include <stdexcept>
#include <string>

class Any {
public:
    Any() = default;
    
    template<typename T>
    Any(const T& value) 
        : m_content(new Holder<T>(value)),
          m_type(typeid(T)) {}
    
    Any(const Any& other) 
        : m_content(other.m_content ? other.m_content->clone() : nullptr),
          m_type(other.m_type) {}
    
    Any& operator=(const Any& other) {
        if (this != &other) {
            m_content.reset(other.m_content ? other.m_content->clone() : nullptr);
            m_type = other.m_type;
        }
        return *this;
    }
    
    Any(Any&& other) noexcept 
        : m_content(std::move(other.m_content)),
          m_type(other.m_type) {}
    
    Any& operator=(Any&& other) noexcept {
        if (this != &other) {
            m_content = std::move(other.m_content);
            m_type = other.m_type;
        }
        return *this;
    }
    
    bool has_value() const {
        return static_cast<bool>(m_content);
    }
    
    std::type_index type() const {
        return m_type;
    }
    
    template<typename T>
    T get() const {
        if (!m_content || m_type != typeid(T)) {
            throw std::bad_cast();
        }
        return static_cast<Holder<T>*>(m_content.get())->value;
    }
    
private:
    struct BaseHolder {
        virtual ~BaseHolder() = default;
        virtual BaseHolder* clone() const = 0;
    };
    
    template<typename T>
    struct Holder : BaseHolder {
        T value;
        Holder(const T& v) : value(v) {}
        BaseHolder* clone() const override {
            return new Holder<T>(value);
        }
    };
    
    std::unique_ptr<BaseHolder> m_content;
    std::type_index m_type;
};

2. 定义统一的函数包装器接口

我们需要一个基类来统一所有函数的调用接口,然后用模板派生类来包装具体的函数:

class FunctionWrapper {
public:
    virtual ~FunctionWrapper() = default;
    virtual Any invoke(const Any& input) const = 0;
};

template<typename In, typename Out>
class SpecificFunctionWrapper : public FunctionWrapper {
public:
    SpecificFunctionWrapper(std::function<Out(In)> func) : m_func(std::move(func)) {}
    
    Any invoke(const Any& input) const override {
        // 检查输入类型是否匹配函数的参数类型
        if (input.type() != typeid(In)) {
            throw std::invalid_argument("Input type mismatch for function");
        }
        // 提取输入值,调用函数,包装结果为Any返回
        In arg = input.get<In>();
        Out result = m_func(arg);
        return Any(result);
    }
    
private:
    std::function<Out(In)> m_func;
};

3. 实现你的容器类

这个容器负责存储函数包装器,并提供链式调用的方法:

class Container {
public:
    template<typename Func>
    void add(Func func) {
        // 自动推断函数的输入输出类型
        using Traits = function_traits<Func>;
        using InType = typename Traits::arg_type;
        using OutType = typename Traits::return_type;
        
        m_wrappers.emplace_back(
            new SpecificFunctionWrapper<InType, OutType>(std::function<OutType(InType)>(func))
        );
    }
    
    Any execute(const Any& initial_input) const {
        Any current_value = initial_input;
        for (const auto& wrapper : m_wrappers) {
            current_value = wrapper->invoke(current_value);
        }
        return current_value;
    }
    
private:
    // 辅助模板:提取函数的参数和返回类型
    template<typename Func>
    struct function_traits;
    
    template<typename Ret, typename Arg>
    struct function_traits<Ret(Arg)> {
        using return_type = Ret;
        using arg_type = Arg;
    };
    
    // 处理函数指针的特化
    template<typename Ret, typename Arg>
    struct function_traits<Ret(*)(Arg)> : function_traits<Ret(Arg)> {};
    
    std::vector<std::unique_ptr<FunctionWrapper>> m_wrappers;
};

4. 测试代码

现在可以用你提到的函数来验证这个方案:

// 定义你提到的三个函数
int h(int x) {
    return x * 2;
}

std::string g(int x) {
    return "Number: " + std::to_string(x);
}

double f(const std::string& s) {
    // 简单示例:返回字符串长度的1.5倍
    return s.size() * 1.5;
}

int main() {
    Container c;
    c.add(h);
    c.add(g);
    c.add(f);
    
    // 初始输入是int类型的4
    Any initial(4);
    Any final_result = c.execute(initial);
    
    // 获取最终的double结果
    std::cout << "Final result: " << final_result.get<double>() << std::endl;
    // 输出应该是:Final result: 13.5(因为"Number: 8"的长度是9,9*1.5=13.5)
    
    return 0;
}

关键原理说明

  • 类型擦除的Any类:通过基类BaseHolder和模板派生类Holder<T>,把任意类型的值包装成统一的Any对象,用std::type_index记录实际类型,全程不需要dynamic_cast。
  • 统一的函数包装器:FunctionWrapper基类提供了统一的invoke接口,模板派生类SpecificFunctionWrapper负责处理具体的输入输出类型匹配,调用时通过type_index检查类型,用static_cast安全提取值(因为已经确认类型匹配)。
  • 自动类型推断:function_traits辅助模板自动提取函数的输入和返回类型,让add方法可以接受任意符合单参数、单返回值的函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:58:10