【问题标题】:General iterable type with specific element type具有特定元素类型的通用可迭代类型
【发布时间】:2013-09-22 04:20:50
【问题描述】:

我正在尝试编写一个用于枚举特定基数的函数,其中数字存储在某种列表中。这是一个例子,取一个 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 类型?

【问题讨论】:

  • 只要把代码写成值类型对就好了。如果有人试图在持有错误类型的容器上调用该函数,他们将得到错误。

标签: c++ c++11


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

【讨论】:

  • 将clang与@IgorTandetnik一起使用会产生非常好的错误(带有std :: string的向量):“对'int'类型的非const左值引用不能绑定到不相关类型'std的值: :__1::basic_string'", (with an int): "'int' 类型的无效范围表达式;没有可行的 'begin' 函数可用"
  • @Lukasz:嗯,这个错误并不完全可怕,但你必须承认,从用户的角度来看,输入std::string 并得到一个关于std::__1::basic_string&lt;char&gt; 的错误仍然很难看。我知道它为什么会发生,但从用户的角度来看,它仍然很糟糕。 Clang 仍有改进的空间。
【解决方案2】:

使用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!如果您在此处输入合理的错误消息,用户将感谢您一千次。

【讨论】:

    【解决方案3】:

    我不会在你的情况下。

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

    最后,返回进位。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 1970-01-01
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多