【问题标题】:checking iterator type in a container template class检查容器模板类中的迭代器类型
【发布时间】:2018-01-22 14:27:09
【问题描述】:

我正在编写一个容器类,并希望提供一个以迭代器为参数的构造函数,但前提是底层迭代类型与容器类型匹配。

所以我写了:

template<typename T>
class Buffer
{
public:
    template <typename InputIter>
    typename std::enable_if<std::is_same<typename std::iterator_traits<InputIter>::value_type, typename T>>::type
    Buffer(InputIter first, InputIter last)
    {
    }
};

但是我有编译错误说模板参数 1 和 2 无效

怎么了?

此处带有编译器的代码:https://onlinegdb.com/SyIqN_mBG

【问题讨论】:

  • 构造函数不应返回任何类型,如果它不是构造函数,则不应与包含它的类同名...
  • 好的,我明白了,我已经从另一个示例中复制/粘贴了 enable_if 行,但没有弄清楚它最后返回了一个类型。但是,我找不到如何使用 enable_if 启用构造函数
  • 把错误信息贴出来供以后参考
  • @W.F.实际上在标准中,构造函数是没有名称的概念成员(因此无法使用类成员访问来调用它们)[class.ctor]/1构造函数没有名称。
  • @Oliv 确实如此,尽管您不能拥有一个函数,其名称为包含它的类,对吗? :)

标签: c++ templates template-meta-programming


【解决方案1】:

差不多了。正如您在 cmets 中所说的那样,您需要记住的是构造函数没有返回类型。 SFINAE 在返回类型上的常用技巧对它们不起作用。

但是它们可以有额外的模板参数,无论如何总是默认的,但是仅仅存在 就可以用于 SFINAE。因此,让我们使用您提供的那个测试(在添加缺少的::value 之后)向 c'tor 添加一个非类型模板参数:

template<typename T>
class Buffer
{
public:
    template <typename InputIter, 
      typename std::enable_if<std::is_same<typename std::iterator_traits<InputIter>::value_type, T>::value, int>::type = 0>
    Buffer(InputIter first, InputIter last)
    {
    }
};

所以如果迭代器是正确的,我们还有一个额外的int = 0,如果不是,SFINAE! c'tor 从重载集中移除。

【讨论】:

  • 我通常会这样写:template&lt;typename InputIter, typename = typename std::enable_if&lt;std::is_same&lt;typename std::iterator_traits&lt;InputIter&gt;::value_type, T&gt;::value&gt;::type&gt;;但是,如果有多个其他相同的模板,这将不起作用(在您的版本中,类型,例如int,可以改变以支持这种情况)。
  • @ArneVogel - IIRC 当条件互斥时,您甚至不需要更改类型。这就是为什么我倾向于这种方法。不过我可能记错了。
  • 非常感谢,这甚至适用于more than two cases!成为一名编译器作者并不容易……
【解决方案2】:

SFINAE 有 3 个可用的地方:

  • 作为返回类型
  • 作为参数类型
  • 作为模板类型

对于构造函数,不能使用返回类型。

我建议默认模板参数:

template<typename T>
class Buffer
{
public:
    template <typename InputIter,
              typename std::enable_if<
                           std::is_same<typename std::iterator_traits<InputIter>::value_type,
                                        T>::value,
                                      bool>::type = false>
    Buffer(InputIter first, InputIter last)
    {
    }
};

【讨论】:

    猜你喜欢
    • 2021-07-29
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2018-05-16
    • 1970-01-01
    相关资源
    最近更新 更多