Reputation: 31
I'd like to write typelist methods to operate with microcontrollers GPIO's.
I'd like to create list of GPIO's and select only pins of specific port.
So, GetPinWithPort
template has specialisation which checks provided type.
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 gives expected result. But gcc - empty list. What is wrong here?
Upvotes: 3
Views: 98
Reputation: 2157
In this line using pina = GetPinWithPort<Porta, TPin<Porta, 1> >::type;
1 has the type of int not uint32_t. So you instantiate GetPinWithPort<Porta, int>
(the non-specialized definition), not GetPinWithPort<Porta, uint32_t>
.
Here is what the specialization should look like to pass the right template parameter to TPin:
template <typename TPort, uint8_t N>
struct GetPinWithPort<TPort, TPin<TPort, N>>
{
using type = TPin<TPort, N>;
};
Here is how it should be used:
using pina = GetPinWithPort<Porta, TPin<Porta, static_cast<uint8_t>(1)> >::type;
The reason for this is that C++ is very strict about using types instide of templates: very limited conversion of types is allowed.
Upvotes: 1
Reputation: 2870
It should be
template <typename TPort, uint8_t N> // or auto
struct GetPinWithPort<TPort, TPin<TPort, N>>
not
template <typename TPort, uint32_t N>
struct GetPinWithPort<TPort, TPin<TPort, N>>
because (I am not a language lawer, it's just how I understand i):
template <class PORT, uint8_t PIN>
class TPin {}
// and
using pina = GetPinWithPort<Porta, TPin<Porta, 1> >::type;
In the specialisation gcc have to choose between:
class T
and
TPin<TPort, uint32_t>
and the type it have is:
TPin<Porta, 1>
So may be gcc resolve the TPin<Porta, 1>
to TPin<Porta, uint8_t>
then fail the specialisation.
Upvotes: 2