c++ - 非常具体的子类方法调用

我有这个设计:
 

class GenericData
{
};

class Data1 : public GenericData
{
};

class Data2 : public GenericData
{
};

class CompBase  
{
public:
    void process()
    {
        // inputs are check to make sure there number and order is correct
        // Use them to automatically call the correct function
        // What here ?
    }
    vector<GenericData> inputs;
};

class Comp1 : public CompBase
{
public:
    void compute(Data1 input1, Data1 input2) { cout << "Comp1::compute(Data1 input1, Data1 input2)" << endl; }
    void compute(Data2 input1, Data2 input2) { cout << "Comp1::compute(Data2 input1, Data2 input2)" << endl; }
    void compute(Data1 input1, Data2 input2) { cout << "Comp1::compute(Data1 input1, Data2 input2)" << endl; }
};

class Comp2 : public CompBase
{
public:
    void compute(Data1 input1) { cout << "Comp2::compute(Data1 input1)" << endl; }
    void compute(Data2 input1) { cout << "Comp2::compute(Data2 input1)" << endl; }
};


具有以下约束:


必须从GenericComp调用计算函数,但此处不能全部声明,因为会有很多(Data1,2和Comp1,2只是示例)
我必须能够收集CompBase
计算功能不一定必须检查其输入(即,不可能将它们传递给相同的结构)
该代码必须足够通用,才能轻松添加其他数据,进行比较和计算


这是一个使用示例:

 
int main() {
    Data1 d1;   Data2 d2;
    Comp1 c1; Comp2 c2;

    c1.inputs = { d1, d1 };
    c1.process();           // "Comp1::compute(Data1 input1, Data1 input2)"

    c1.inputs = { d2, d2 };
    c1.process();           // "Comp1::compute(Data2 input1, Data2 input2)"

    c1.inputs = { d1, d2 };
    c1.process();           // "Comp1::compute(Data1 input1, Data2 input2)"

    vector<GenericComp> comps = { c1, c2 };
    for (comp : comps)
    {
        comp.process();
    }
    return 0;
}


我有一个here的“工作”示例。

我尝试了不同的方法:CRTP,可变参数模板函数,currying和部分应用程序以及大量使用谷歌搜索功能,但我一直陷于此。

这些约束可能吗?如果是这样,您该怎么做?

最佳答案

谢谢你们的回答。
@Daniel Jour,您的帖子对我有很大帮助,我做了一些修改以适合我的情况。

Here是适用于我的更新示例。

 

#include <iostream>
#include <vector>
#include <map>
#include <functional>
#include <memory>
using namespace std;

class GenericData
{
public:
    virtual ~GenericData() {};
};

class Data1 : public GenericData
{
public:
    virtual ~Data1() {};
};

class Data2 : public GenericData
{
public:
    virtual ~Data2() {};
};

class GenericComp
{
public:
    virtual ~GenericComp() {};
    vector<GenericData*> inputs;
};

class Comp1 : public GenericComp
{
public:
    static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data1> const & input2) { cout << "Comp1::compute(Data1 input1, Data1 input2)" << (input2 ? "ok" : "null") << endl; return true; }
    static bool compute(shared_ptr<Data2> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data2 input1, Data2 input2)" << endl; return true; }
    static bool compute(shared_ptr<Data1> const & input1, shared_ptr<Data2> const & input2) { cout << "Comp1::compute(Data1 input1, Data2 input2)" << endl; return true; }
};

class Comp2 : public GenericComp
{
public:
    static bool compute(shared_ptr<Data1> const & input1) { cout << "Comp2::compute(Data1 input1)" << endl; return true; }
    static bool compute(shared_ptr<Data2> const & input1) { cout << "Comp2::compute(Data2 input1)" << endl; return true; }
};

// Arguments type to the function "interface"
using Arguments = std::vector<shared_ptr<GenericData>> const &;
// the interface
using Function = std::function<bool (Arguments)>;

// Base case of packing a function.
// If it's taking a vector and no more
// arguments, then there's nothing left to
// pack.
template<std::size_t N, typename Fn>
Function pack(Fn && fn)
{
    return [fn = std::forward<decltype(fn)>(fn)] (Arguments arguments)
    {
        if (N != arguments.size())
        {
            throw std::string{"wrong number of arguments, expected "} +
              std::to_string(N) +
              std::string{" but got "} +
              std::to_string(arguments.size());
        }
        return fn(arguments);
    };
}

// pack a function to a function that takes
// it's arguments from a vector, one argument after
// the other.
template<std::size_t N, typename Arg, typename... Args, typename Fn>
Function pack(Fn && fn)
{
    return pack<N+1, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args)
    {
        try
        {
            return fn(arguments, arguments.at(N), args...);
        }
        catch (std::bad_cast const &)
        {
            throw std::string{"argument "} + std::to_string(N) + std::string{" has wrong type "};
        }
    });
}

// transform a function into one that takes its
// arguments from a vector
template<typename... Args, typename Fn>
Function pack_function(Fn && fn)
{
    return pack<0, Args...>([fn = std::forward<decltype(fn)>(fn)] (Arguments arguments, Args const &... args) -> bool
    {
        return fn(args...);
    });
}

int main() {
    // Pack all the functions
    std::map<std::string, Function> operations;
    operations["Comp1_Data1_Data1"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
    {
        return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data1>(i2));
    });
    operations["Comp1_Data2_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
    {
        return Comp1::compute(dynamic_pointer_cast<Data2>(i1), dynamic_pointer_cast<Data2>(i2));
    });
    operations["Comp1_Data1_Data2"] = pack_function<shared_ptr<GenericData>, shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1, shared_ptr<GenericData> const & i2)
    {
        return Comp1::compute(dynamic_pointer_cast<Data1>(i1), dynamic_pointer_cast<Data2>(i2));
    });
    operations["Comp2_Data1"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
    {
        return Comp2::compute(dynamic_pointer_cast<Data1>(i1));
    });
    operations["Comp2_Data2"] = pack_function<shared_ptr<GenericData>>([] (shared_ptr<GenericData> const & i1)
    {
        return Comp2::compute(dynamic_pointer_cast<Data2>(i1));
    });

    // Create the possible inputs
    vector<shared_ptr<GenericData>> data1_data1 { shared_ptr<Data1>(), shared_ptr<Data1>() };
    vector<shared_ptr<GenericData>> data2_data2 { shared_ptr<Data2>(), shared_ptr<Data2>() };
    vector<shared_ptr<GenericData>> data1_data2 { shared_ptr<Data1>(), shared_ptr<Data2>() };
    vector<shared_ptr<GenericData>> data1 { shared_ptr<Data1>() };
    vector<shared_ptr<GenericData>> data2 { shared_ptr<Data2>() };

    // The calls !
    operations["Comp1_Data1_Data1"](data1_data1);
    operations["Comp1_Data2_Data2"](data2_data2);
    operations["Comp1_Data1_Data2"](data1_data2);
    operations["Comp2_Data1"](data1);
    operations["Comp2_Data2"](data2);

    // Wrong arguments
    try
    {
        operations["Comp1_Data1_Data1"](data1);
    }
    catch (std::string const & e)
    {
        cout << e << endl;
    }
    try
    {
        operations["Comp2_Data1"](data1_data1);
    }
    catch (std::string const & e)
    {
        cout << e << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值