c++ - 哪种模式可以生成具有不同 Tor 参数的对象的实例化
问题描述
我想构建一个有或没有工具、移动底座和其他部件的机器人。由于我想自动化零件的配置,我有一个机器人类,其中零件作为模板参数
例如,在下面的代码中,只要我们使用与 ToolInterface 具有相同构造函数签名的工具,代码就会构建。它确实是用螺丝刀建造的,但不是用夹持器建造的。
#include <iostream>
#include <string>
class BaseRobot
{
public:
BaseRobot(){};
};
class ToolInterface
{
public:
ToolInterface(BaseRobot* _base, std::string _name):name{_name}{/*register _base*/};
std::string name;
bool param_1;
char param_2;
};
template<class T, class... Args>
constexpr T* construct(Args... args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return new T(args...);
}
};
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
Robot():tool(construct<Tool>(this, "tool")){ // <--- here is my problem !!
if constexpr (! std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver: public ToolInterface
{
public:
Screwdriver(BaseRobot* _base, std::string _name):ToolInterface(_base, _name){};
};
class Gripper: public ToolInterface
{
public:
Gripper(BaseRobot* _base, std::string _name, bool _reversed):
ToolInterface(_base, _name)
,reversed{_reversed}{};
bool reversed;
};
int main()
{
Robot<Screwdriver> robot_screwdriver;
Robot<nullptr_t> robot_null;
//Robot<Gripper> robot_gripper; //does not build
return 0;
}
这里有一些想法:
- 使用作为工具参数传递的 ToolConfig 结构。如果一个工具需要更多参数,则应该继承 ToolConfig 并将其转换为工具构造函数(见下文):该死,看起来既麻烦又丑陋!
- 强制继承 ToolInterface 类的 Ctor 签名:一些工具必须有不同的 Ctor 签名
- 使用可变参数模板将参数传递给模板:不合理,因为最后,我想要类似的东西
template<class Tool1, class Tool2, class MobileBase, class Camera> class Robot
解决方案 1 看起来像
struct ToolConfig
{
std::string name;
};
struct GripperConfig : public ToolConfig
{
bool reversed;
};
class Gripper : public ToolInterface
{
public:
Gripper(ToolConfig& _config):
ToolInterface(_config)
,reversed{static_cast<GripperConfig&>(_config).reversed}{};
bool reversed;
};
你有一个神奇的模式来解决我的问题吗?我的模式错了吗?
解决方案
您也可以使用 tuple 代替 struct,虽然不理想,但这也可以:
#include <iostream>
#include <string>
#include <tuple>
class BaseRobot
{
public:
BaseRobot() {};
};
class ToolInterface
{
public:
ToolInterface(std::string _name) :name{ _name } {/*register _base*/ };
std::string name;
bool param_1;
char param_2;
};
template <typename T, typename ... Types, std::size_t ... Indices>
constexpr T* apply_impl(const std::tuple<Types...>& tuple, std::index_sequence<Indices...>)
{
return new T(std::get<Indices>(tuple)...);
}
template <typename T, typename ... Types>
constexpr T* apply(const std::tuple<Types...>& tuple)
{
return apply_impl<T>(tuple, std::index_sequence_for<Types...>());
}
template<class T, class... Args>
constexpr T* construct(std::tuple<Args...> args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return apply<T>(args);
}
}
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
template<class ...Args1> //, class ...Args2>
Robot(std::tuple<Args1...> p1): // , std::tuple<Args2...> p2):
tool(construct<Tool>(p1))
{ // <--- here is my problem !!
if constexpr (!std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver : public ToolInterface
{
public:
Screwdriver(std::string _name) :ToolInterface(_name) {};
};
class Gripper : public ToolInterface
{
public:
Gripper(std::string _name, bool _reversed) :
ToolInterface(_name)
, reversed{ _reversed }{};
bool reversed;
};
int main()
{
using p1 = std::tuple<std::string>;
Robot<Screwdriver> robot_screwdriver(p1{"sdvr"});
return 0;
}
可以改进我同意。
推荐阅读
- node.js - Node.js - 将文件发送到 Facebook Graph Api
- c++ - Boost union 在 1.67 中不起作用,但在 1.61 中起作用。为什么?
- c# - 如何在asp.net c#的下拉列表中显示JSON数组数据?
- php - 如何测试 Symfony 独立包
- javascript - “npm add”和“npm install --save”之间的区别?
- npm - 范围包与纱线的依赖关系
- linux - 使用循环解析 ksh 中的长参数和短参数
- r - R按POSIXct时间和条件过滤/选择数据
- javascript - 改变状态,然后清除输入反应
- c# - 是否可以在使用实体框架的应用程序上执行 SQL 注入?