【问题标题】:Templated iterator for a std::vectorstd::vector 的模板化迭代器
【发布时间】:2018-04-27 21:55:13
【问题描述】:

我正在创建一个实用函数来根据模板类型将字节数组组合成一个值。

我目前有两个重载函数,它们接受一对正向迭代器和一对反向迭代器,以便处理大端和小端。

是否可以有一个模板化的向量迭代器并将我的两个函数简化为一个?

例如,这是我想做的:

template <typename T, typename Iter>
inline T combine_bytes(std::vector<unsigned char>::Iter const &start,
                       std::vector<unsigned char>::Iter const &end,
                       bool bigendian)
{
    T ret;
    std::copy(start, end, reinterpret_cast<unsigned char *>(&ret));

    return ret;
}

我得到的编译错误是:

Failed to specialize function template 'T Utils::combine_bytes(const Iter &, const Iter &)'

【问题讨论】:

    标签: c++ c++11 templates vector


    【解决方案1】:

    您可以使用static_assert 来确保您的迭代器引用的类型是unsigned char。那么你就不用担心被迭代的是什么类型的容器了:

    template <typename T, typename Iter>
    inline T combine_bytes(Iter start, Iter end)
    {
        static_assert(std::is_same<std::decay_t<decltype(*start)>, unsigned char>::value,
                      "Must use unsigned char");
        T ret;
        std::copy(start, end, reinterpret_cast<unsigned char *>(&ret));
    
        return ret;
    }
    

    当您使用它时,您可能需要添加一些运行时检查以确保 std::distance(begin, end) == sizeof(T),如果您不只是为了保持示例简短而忽略它。

    【讨论】:

    • 这种方法是否使用 SFINAE?我猜没有。
    • 要编译它,我需​​要将static_assert 中要检查的类型更改为unsigned char &amp;。所以现在看起来像这样:static_assert(std::is_same&lt;decltype(*start), unsigned char &amp;&gt;::value, "Must use unsigned char");
    • @ctzdev 哎呀。您可以使用std::decay_t&lt;decltype(*start)&gt; 而不仅仅是decltype(*start)。从技术上讲,这比使用 unsigned char&amp; 更正确,因为它将接受只读迭代器,但差别很小。
    【解决方案2】:

    我想,使用 SFINAE,你可以写如下内容

    template <typename T, typename Iter>
    inline typename std::enable_if<
          std::is_same<Iter, std::vector<unsigned char>::iterator>{}
       || std::is_same<Iter, std::vector<unsigned char>::reverse_iterator>{},
       T >::type combine_bytes (Iter const & start,
                                Iter const & end,
                                bool bigendian)
    {
        T ret;
        std::copy(start, end, reinterpret_cast<unsigned char *>(&ret));
    
        return ret;
    }
    

    即:为泛型模板类型Iter定义函数并仅在Iterstd::vector&lt;unsigned char&gt;::iteratorstd::vector&lt;unsigned char&gt;::reverse_iterator时启用它

    【讨论】:

    • 与 Miles Budnek 的方法相比,这种方法有什么额外的好处吗?
    • @ctzdev - 不一定;取决于您的要求;如果您为不同的类型准备不同的功能,我想最好使用std::enable_if 以避免歧义或避免首选错误的版本。如果您有一个简单的案例,其中只有一个函数只能与一组类型一起使用,我认为static_assert() 是一个更简单且足够好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 2016-11-07
    相关资源
    最近更新 更多