0

我正在尝试编写一个用于枚举特定基数的函数,其中数字存储在某种列表中。这是一个示例,采用 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() 的类型。有没有办法用 begin() 和 end() 来表示 num 可以是任何东西,但它的元素必须具有 unsigned int 类型?

4

3 回答 3

1

如果你真的想检查这个,试试:

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 正确指出您可能根本不需要明确检查。如果您传递一个真正无法使用的类型,编译器会给您一个(丑陋的)错误。

于 2013-09-22T04:55:45.777 回答
0

我不会在你的情况下。

将进位改为一本书,使用 ++ 代替 +=,将 base 设为 T 类型,并将 n 设为auto&

最后,返回携带。

您的代码现在完全符合要求。

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

这让您的代码可以处理无符号整数、多项式、大整数等。

于 2013-09-22T22:42:03.073 回答
0

用 a 编写一个通用函数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简称)。如果 与ValueType不匹配Container::value_type,则此模板不会形成有效的函数定义,因此会被忽略。编译器表现得好像没有这样的函数。即,用户不能使用无效的Container 和ValueType 组合的函数。

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

于 2013-09-22T08:36:25.933 回答