c++ - 是否可以从可变参数模板调用多个基类构造函数?
问题描述
我正在尝试为我正在处理的嵌入式项目中的外围设备创建一个抽象。问题是,并非所有人都以相同的方式行事,也没有相同的界面。
我正在尝试将 CRTP 与静态装饰器设计模式一起使用,但我被困在 CommunicableDevice 构造函数上,因为我不知道如何使用可变参数模板调用多个基类构造函数。
#include <iostream>
struct Interface
{
Interface(int pin) {}
virtual void write()
{
}
virtual void read()
{
}
};
struct RTSCTSInterface : public Interface
{
template <typename ... Args>
RTSCTSInterface(int rts, Args&& ... args)
: Interface(std::forward<Args>(args)...), rts(rts)
{}
void write() override
{
}
int rts;
};
struct Powerable
{
Powerable(int dummy) : dummy(dummy)
{}
void turnOn()
{
}
int dummy;
};
struct Device
{
Device(const std::string& name) : name(name){}
std::string name;
};
template <typename CustomDevice>
struct PowerableDevice : public Powerable, public CustomDevice
{
template <typename ... Args>
PowerableDevice(int dummy, Args&&... args)
: Powerable(dummy), CustomDevice(std::forward<Args>(args)...)
{}
};
template <typename CustomInterface, typename CustomDevice>
struct CommunicableDevice : public CustomInterface, public CustomDevice
{
template <typename ... Args>
CommunicableDevice(Args&&... args)
// call constructors with args
{
}
};
int main()
{
CommunicableDevice<RTSCTSInterface, PowerableDevice<Device>> dev(1, 2, 300, 5, "dummy");
}
真的有可能吗?如果是这样,我该怎么做?我也愿意接受有关如何解决此问题的建议。
解决方案
我不知道如何使用可变参数模板调用多个基类构造函数。
template <typename CustomInterface, typename CustomDevice>
struct CommunicableDevice : public CustomInterface, public CustomDevice
{
template <typename ... Args>
CommunicableDevice(Args&&... args)
// call constructors with args
{
}
};
我没有看到一个通用的解决方案。
问题是:哪个参数用于第一个基类,哪个参数用于第二个?
我想到的唯一解决方案是将每个基类的参数包装在std::tuple
. 然后使用委托构造函数和索引序列来提取它们。
我的意思是(简化示例:没有完美的转发)
template <typename CI, typename CD>
struct foo : public CI, public CD
{
private:
template <typename ... As, typename ... Bs, std::size_t ... Ia,
std::size_t ... Ib>
foo (std::tuple<As...> const & ta, std::tuple<Bs...> const & tb,
std::index_sequence<Ia...>, std::index_sequence<Ib...>)
: CI(std::get<Ia>(ta)...), CD(std::get<Ib>(tb)...)
{ }
public:
template <typename ... As, typename ... Bs>
foo (std::tuple<As...> const & ta, std::tuple<Bs...> const & tb)
: foo(ta, tb, std::index_sequence_for<As...>{},
std::index_sequence_for<Bs...>{})
{ }
};
不好的部分是你必须调用构造元组
foo<bar1, bar2> f{std::make_tuple(1, 2l, "3", 4ull), // <-- for bar1
/* for bar2 --> */std::make_tuple(5, "6", std::vector<int>{7, 8, 9})};
下面是一个完整的 C++14 编译示例
#include <tuple>
#include <string>
#include <vector>
#include <type_traits>
template <typename CI, typename CD>
struct foo : public CI, public CD
{
private:
template <typename ... As, typename ... Bs, std::size_t ... Ia,
std::size_t ... Ib>
foo (std::tuple<As...> const & ta, std::tuple<Bs...> const & tb,
std::index_sequence<Ia...>, std::index_sequence<Ib...>)
: CI(std::get<Ia>(ta)...), CD(std::get<Ib>(tb)...)
{ }
public:
template <typename ... As, typename ... Bs>
foo (std::tuple<As...> const & ta, std::tuple<Bs...> const & tb)
: foo(ta, tb, std::index_sequence_for<As...>{},
std::index_sequence_for<Bs...>{})
{ }
};
struct bar1
{
template <typename ... Ts>
bar1 (int, long, Ts...)
{ }
};
struct bar2
{
template <typename ... Ts>
bar2 (int, std::string, Ts...)
{ }
};
int main ()
{
foo<bar1, bar2> f{std::make_tuple(1, 2l, "3", 4ull),
std::make_tuple(5, "6", std::vector<int>{7, 8, 9})};
}
推荐阅读
- vue.js - 访问 getter 中的状态属性
- angular - Angular:显示不受支持的 IE 版本而不是白屏
- javascript - 在函数内等待/观察
- android - Kotlin - 类型不匹配所需的集合找到列表
- javascript - 如何在命令行中传递参数以运行纱线脚本
- java - Java Spring refcursor queries slows down
- hp-nonstop - Is there a grep equivalent in TACL on HP-Nonstop?
- tor - 如何在 mac 上安装 obfs4proxy?
- java - 第二次尝试打开Shell时如何修复Widget配置错误?
- php - 在共享主机上托管 Laravel elasticsearch 项目