具有特定元素类型的常规可迭代类型

General iterable type with specific element type

本文关键字:类型 迭代 常规可 元素      更新时间:2023-10-16

我正在尝试编写一个函数,用于枚举特定基数的数字,其中数字存储在某种列表中。下面是一个例子,取一个 std::vector

void next_value(std::vector<unsigned int> &num, unsigned int base) {
   unsigned int carry = 1;
   for (unsigned int &n: num) {
       n += carry;
       if (n >= base) {
           carry = 1;
           n = 0;
       } else {
           carry = 0;
       }
   }
}
num 向量不一定

是向量,它可以是一个数组,或者实际上任何定义了 std::begin() 和 std::end() 的类型。有没有办法表达 num 可以是带有 begin() 和 end() 的任何内容,但它的元素必须具有无符号的 int 类型?

如果您确实要检查这一点,请尝试:

template <class Sequence>
void next_value(Sequence &num, unsigned int base) {
    static_assert(boost::is_same<Sequence::value_type, unsigned>::value, "foo");
    // ...

如果您尚未使用 C++11,请改用BOOST_STATIC_ASSERT。

如果需要支持纯 C 样式数组,则需要做更多的工作。

另一方面,@IgorTandetnik正确地指出,您可能根本不需要明确检查。 如果您传递了一个真正无法使用的类型,编译器会给你一个(丑陋的)错误。

使用 static_assert 编写泛型函数是个好主意,因为您可以为用户提供有用的错误消息,而不是"foo"。

但是,还有另一种使用C++11的方法:

template <typename Container, typename ValueType>
typename std::enable_if<std::is_same<Container::value_type, ValueType>::value, void>::type
   next_value(Container& num, ValueType base)
{
  // ... 
}

如果您以前从未见过,这是一种相当神秘的方法。这使用"替换失败不是错误"(简称SFINAE)。如果ValueTypeContainer::value_type不匹配,则此模板不会形成有效的函数定义,因此将被忽略。编译器的行为就像没有这样的函数一样。即,用户不能将函数与容器和 ValueType 的无效组合一起使用。

请注意,我确实建议使用static_assert!如果你在那里放一个合理的错误消息,用户会感谢你一千次。

在您的情况下,我不会。

将进位更改为书籍,使用 ++ 而不是 +=,使 base 成为类型 T,n 成为auto&

最后,返回携带。

您的代码现在完全可以键入要求。

如果需要诊断,请静态断言操作对自定义错误消息有意义。

这让你的代码处理无符号的整数、多项式、bigint 等等。