我想编写类型列表方法以与微控制器GPIO配合使用。
我想创建GPIO列表并仅选择特定端口的引脚。
因此,GetPinWithPort
模板具有专门检查提供的类型的模板。
template <typename... Ts>
struct tlist
{
using type = tlist;
};
template <typename T> class debug_t;
#define MAKE_PORT(NAME, ID)\
class NAME\
{\
public:\
static void Set(uint32_t v) { };\
static void Reset(uint32_t v) { };\
enum { id = ID };\
};
MAKE_PORT(Porta, 'A');
MAKE_PORT(Portb, 'B');
template <class PORT, uint8_t PIN>
class TPin
{
public:
static void Set() { PORT::Set(1 << PIN); }
static void Reset() { PORT::Reset(1 << PIN); }
typedef PORT port;
enum { pin = PIN };
};
template <class TPort, class T>
struct GetPinWithPort {
using type = tlist<>;
};
template <typename TPort, uint32_t N>
struct GetPinWithPort<TPort, TPin<TPort, N>>
{
using type = TPin<TPort, N>;
};
int main()
{
using pina = GetPinWithPort<Porta, TPin<Porta, 1> >::type;
// std::cout << typeid(pina).name() << std::endl; //Visual Studio gives: class TPin<class Porta,1>
debug_t<pina> d; //gcc output: tlist<>
}
Visual Studio提供了预期的结果。但海湾合作委员会-空列表。 怎么了?
答案 0 :(得分:2)
应该是
template <typename TPort, uint8_t N> // or auto
struct GetPinWithPort<TPort, TPin<TPort, N>>
不是
template <typename TPort, uint32_t N>
struct GetPinWithPort<TPort, TPin<TPort, N>>
因为(我不是语言律师,这就是我的理解方式):
template <class PORT, uint8_t PIN>
class TPin {}
// and
using pina = GetPinWithPort<Porta, TPin<Porta, 1> >::type;
在专业化中,gcc必须在以下选项之间进行选择:
class T
和
TPin<TPort, uint32_t>
及其类型为:
TPin<Porta, 1>
所以gcc可能会将TPin<Porta, 1>
解析为TPin<Porta, uint8_t>
,然后使专业化失败。
答案 1 :(得分:1)
在此行using pina = GetPinWithPort<Porta, TPin<Porta, 1> >::type;
1具有int类型而不是uint32_t。因此,您实例化了GetPinWithPort<Porta, int>
(非专业定义),而不是GetPinWithPort<Porta, uint32_t>
。
以下是专业化将正确的模板参数传递给TPin的外观:
template <typename TPort, uint8_t N>
struct GetPinWithPort<TPort, TPin<TPort, N>>
{
using type = TPin<TPort, N>;
};
这里是应如何使用它:
using pina = GetPinWithPort<Porta, TPin<Porta, static_cast<uint8_t>(1)> >::type;
这样做的原因是C ++在使用模板类型方面非常严格:允许非常有限的类型转换。