为什么不能推导嵌套在模板类中的枚举的模板参数?

时间:2013-01-28 09:50:28

标签: c++ templates c++11

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

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'

1 个答案:

答案 0 :(得分:14)

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

“但那太傻了!”你会说; “很明显,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属于同一类型。

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