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

Posted

技术标签:

【中文标题】为啥不能推导出嵌套在模板类中的枚举的模板参数?【英文标题】:Why can't the template parameters for enums nested in a template class be deduced?为什么不能推导出嵌套在模板类中的枚举的模板参数? 【发布时间】:2013-01-28 09:50:28 【问题描述】:

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

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'

【问题讨论】:

是的,添加typenmae 修复了该错误,但现在我得到no matching function for call to 'USART::USART(usart&lt;1&gt;::tx, usart&lt;1&gt;::rx)' @sbi:我没有立即看到这与我的问题之间的联系 嗯。既然还没有人回答,你为什么不相应地改变你的问题呢?请指出确切的错误消息发生在哪里。我很抱歉现在投票接近。如果可以的话,我会收回它。 这是非推断上下文。基本上,您不能指望从Foo&lt;X&gt;::Y 检索X @R.MartinhoFernandes: 也许usart&lt;N&gt; 可以包含一个接受usart&lt;N&gt;::tx 并返回类型usart&lt;N&gt; 的免费朋友函数。然后如果USART 执行decltype(that_function(pin_tx)),它会得到一个类型,可以从中推导出N。如果有人在你的回答中做了这件事,那么推论出1(如果他们也没有定义朋友)或者调用是模棱两可的(如果他们这样做了),这会诊断出他们的错误。不过,我不太确定如何将所有这些放在一起,但它可能需要额外的 USART 间接级别。 【参考方案1】:

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

“但这很愚蠢!”你会说; “很明显,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&lt;4321&gt;::txusart&lt;1&gt;::tx是同一种类型。

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

【讨论】:

这很有意义。我想我会求助于usart1::txusart2:tx 等的重载,因为我并没有真正从这里的模板参数中获得任何东西。

以上是关于为啥不能推导出嵌套在模板类中的枚举的模板参数?的主要内容,如果未能解决你的问题,请参考以下文章

gcc 编译错误:模板类表中嵌套类 A ​​的成员在嵌套朋友类中不可见。为啥?

如何使用在同一类的基模板中的类中声明的枚举

为啥这个嵌套的可变参数模板是无效参数?

接收 std::pair 作为参数并从花括号列表初始化推导出类型的模板化函数

为啥嵌套在模板中的每个都不输出

为啥成员函数不能用作模板参数?