我正在尝试为我正在从事的嵌入式项目中的外围设备创建抽象。问题是,并非所有人都表现出相同的行为方式,也不具有相同的界面。
我正在尝试将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");
}
实际上有可能吗?如果是这样,我该怎么办?我也欢迎提出有关如何解决此问题的建议。
答案 0 :(得分:2)
我不知道如何使用可变参数模板调用多个基类构造函数。
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})};
}