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

时间:2013-09-22 04:20:51

标签: c++ c++11

我正在尝试编写一个函数来枚举一些特定的基数,其中数字存储在某种列表中。这是一个例子,采用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 vector不一定需要是一个vector,它可以是一个数组,或者实际上是为它定义了std :: begin()和std :: end()的任何类型。有没有办法表达num可以是begin()和end()的任何东西,但它的元素必须有unsigned int类型?

3 个答案:

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

答案 1 :(得分:0)

使用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不匹配,则此模板不会形成有效的函数定义,因此会被忽略。编译器的行为就好像没有这样的功能。即,用户不能将该函数与Container和ValueType的无效组合一起使用。

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

答案 2 :(得分:0)

我不会在你的情况下。

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

最后,返回进行。

您的代码现在正好符合要求。

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

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