Why can't the template parameters be inferred for enums nested in the template class?
I have some constants named like this:
template<int n> class usart {
private:
usart();
public:
enum class tx {};
enum class rx {};
enum class ck {};
};
template<> class usart<1> {
public:
enum class tx { A9 = gpio::A9, C4 = gpio::C4 };
enum class rx { A10 = gpio::A10, C5 = gpio::C5 };
enum class ck { A8 = gpio::A8 };
};
// two more of these
where gpio
is just the simplest integer enumeration.
I would like to apply some type safety on my class in another file:
class USART {
public:
template<int N>
USART(typename usart<N>::tx pin_tx, typename usart<N>::rx pin_rx) {
//This signature enforces correct pins with types, doesn't it?
}
};
However, when I use this with
USART us = USART(usart<1>::tx::A9, usart<1>::rx::A10);
<s> I am getting error
error: expected ')' before 'pin_tx'
Why is this syntax illegal?
EDIT :typename
Now it gives me this error when I try to instantiate the class:
error: no matching function for call to 'USART::USART(usart<1>::tx, usart<1>::rx)'
note: template<int N> USART::USART(typename usart<N>::tx, typename usart<N>::rx)
note: template argument deduction/substitution failed:
note: couldn't deduce template parameter 'N'
source to share
Template parameters used in function arguments are not deduced because the arguments are of dependent types.
"But this is stupid!" you would say; "Obviously N is 1! Why can't the compiler do this?"
Consider the following:
template<> class usart<4321> {
public:
typedef usart<1>::tx tx;
typedef usart<1>::rx rx;
typedef usart<1>::ck ck;
};
Should N be 1 or 4321? After all, usart<4321>::tx
both usart<1>::tx
are the same type.
The compiler cannot know what N should be without checking that only one instance of usart is of the exact type as the member tx
. This would require too many instances or too complex logic to prove that no amount of instantiation would result in what is in the general case. Of course, it would be easy to implement something for this specific case, but this is not very useful for all other cases. The C ++ committee simply decided not to require this from the compiler authors.
source to share