首页 文章

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

提问于
浏览
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()的任何类型 . 有没有办法表示num可以是begin()和end()的任何东西,但它的元素必须有unsigned int类型?

3 回答

  • 0

    如果你真的想检查一下,试试:

    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

    在你的情况下,我不会 .

    改变携带到书,使用而不是=,使基数为类型T,并且n为 auto& .

    最后,返回进位 .

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

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

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

  • 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)
    {
      // ... 
    }
    

    如果您以前从未见过这种方法,这是一种相当神秘的方法 . 这使用"Substitution failure is not an error"(简称 SFINAE ) . 如果 ValueTypeContainer::value_type 不匹配,则此模板不会形成有效的函数定义,因此会被忽略 . 编译器的行为就好像没有这样的功能 . 即,用户不能将该函数与Container和ValueType的无效组合一起使用 .

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

相关问题