用于从流中读取std :: vector <t>的模板函数

时间:2018-08-21 23:13:39

标签: c++

我有一个模板ReadVector函数,该函数从流中读取std :: vector:

    template <class Stream, typename T>
    inline void ReadVector(Stream & s, std::vector<T> & items)
    {
        s.Read(reinterpret_cast<uint8_t *>(items.data()), items.size() * sizeof(T));
    }

具有布尔向量的专门化:

    template <class Stream>
    void ReadVector(Stream & s, std::vector<bool> & x)
    {
    ...
    }

上面的代码可以编译,但是我想仅在T是算术类型的情况下才调用第一个函数,因此条件应该是这样的:

std::enable_if<std::is_arithmetic<T>::value && !std::is_same(T, bool)::value

但是我不知道语法是什么。

如果T不是布尔值也不是算术的话,我还想对ReadVector进行另一种专门化。

我的第一个想法是这样的:

    template <class Stream, typename T>
    void ReadVector(Stream & s, std::vector<T> & items);

    template <class Stream, typename T>
    typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type ReadVector(Stream & s, std::vector<T> & items)
    {
    ...
    }

但这会导致对重载函数的歧义调用。

2 个答案:

答案 0 :(得分:2)

解决了这个问题!

    template <class Stream, typename T>
    typename std::enable_if<std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type ReadVector(Stream & s, std::vector<T> & v)
    {
        s.Read(reinterpret_cast<uint8_t *>(v.data()), v.size() * sizeof(T));
    }

    template <class Stream, typename T>
    typename std::enable_if<std::is_class<T>::value, void>::type ReadVector(Stream & s, std::vector<T> & v)
    {
        for (auto & elem : v)
        {
            Read(s, elem);
        }
    }

    template <class Stream>
    void ReadVector(Stream & s, std::vector<bool> & x)
    {
    ...
    }

答案 1 :(得分:1)

我认为您的方法是错误的!

为什么不只使用向量构造函数?

std::vector<int>  v(std::istream_iterator<int>(stream), std::istream_iterator<int>());

可以在向量初始值设定项中完成的功能不需要它。

如果您想做点花哨的事情(例如从流中读取原始数据),只需定义一个类以读取该特定类型的数据即可。

struct RawDataToInt
{
     int  value;
     operator int() {return value;}
     friend std::istream& operator>>(std::istream& str, RawDataToInt& v)
     {
         return str.read(reinterpret_cast<char*>(&v.value), sizeof(int));
     }
};
....
std::vector<int>  v(std::istream_iterator<RawDataToInt>(stream), std::istream_iterator<RawDataToInt>());