简体   繁体   中英

Why can't the template parameters for enums nested in a template class be deduced?

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 a simple integer enum.

I'd like to enforce 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);

I get the error

 error: expected ')' before 'pin_tx' 

Why is this syntax illegal? EDIT : typename

This now gives me this error when I try and 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' 

The template parameters used in the function arguments are not deducible because the the arguments are of dependent types.

"But that's silly!" you would say; "It is obvious that N is 1! Why can't the compiler have the smarts to deduce that?"

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 and usart<1>::tx are the same type.

The compiler cannot know what N should be without checking that only one instantiation of usart has that exact type as the tx member. This would either require too many instantiations or way too complex logic to prove that no instantiation would result in that in the general case. Sure, it might be simple to implement something for this particular case, but that isn't terribly useful for all other cases. The C++ committee simply decided to not require this of compiler writers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM