为什么无法推导出嵌套在模板类中的枚举的模板参数?

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

本文关键字:枚举 参数 嵌套 为什么      更新时间:2023-10-16

我有一些常量是这样命名的:

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

其中gpio只是一个简单的整数枚举。

我想在另一个文件中对我的类强制实施某种类型安全:

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?
    }
};

但是,当我将其与

USART us = USART(usart<1>::tx::A9, usart<1>::rx::A10);

我收到错误

error: expected ')' before 'pin_tx'

为什么此语法是非法的?编辑typename

现在,当我尝试实例化类时,这给了我这个错误:

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'

函数参数中使用的模板参数不可推导,因为这些参数是依赖类型。

"但这很愚蠢!"你会说;"很明显,N是1!为什么编译器不能有智慧来推断这一点呢?

请考虑以下事项:

template<> class usart<4321> {
public:
    typedef usart<1>::tx tx;
    typedef usart<1>::rx rx;
    typedef usart<1>::ck ck;
};

N 应该是 1 还是 4321?毕竟,usart<4321>::txusart<1>::tx是同一类型。

编译器无法知道 N 应该是什么,除非检查 usart 只有一个实例具有与tx成员完全相同的类型。这要么需要太多的实例化,要么需要太复杂的逻辑来证明在一般情况下没有实例化会导致这种情况。当然,为这种特殊情况实现一些东西可能很简单,但这对所有其他情况并不是很有用。C++委员会只是决定不要求编译器编写者这样做。