【问题标题】: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 间接级别。

标签: c++ templates c++11


【解决方案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 等的重载,因为我并没有真正从这里的模板参数中获得任何东西。
猜你喜欢
  • 2017-07-03
  • 2018-12-09
  • 2012-12-06
  • 2011-08-28
  • 2014-03-21
  • 2022-11-01
  • 1970-01-01
  • 2012-03-13
相关资源
最近更新 更多