4

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

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

wheregpio只是一个简单的整数枚举。

我想在另一个文件中对我的类强制执行一些类型安全:

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'
4

1 回答 1

15

函数实参中使用的模板形参是不可推导的,因为实参属于依赖类型。

“但那很愚蠢!” 你会说;“很明显,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都是同一类型。

tx如果不检查是否只有一个 usart 实例具有该确切类型作为成员,编译器就无法知道 N 应该是多少。这将需要太多的实例化或过于复杂的逻辑来证明在一般情况下没有实例化会导致这种情况。当然,为这种特殊情况实现某些东西可能很简单,但这对于所有其他情况并不是非常有用。C++ 委员会只是决定不要求编译器编写者这样做。

于 2013-01-28T10:09:15.363 回答