std ::转换为任意容器

std ::转换为任意容器

问题描述:

我想编写一个通用函数,该函数接收值为 [a1,..,an] container1 ,并返回另一个值为 [convert(a1),..,convert(an)] .如果 container2 std :: vector ,那么问题就微不足道, std :: transform 正是我想要的.以下函数可以处理任意 container2 container1

I want to write universal function that receives container1 with values [a1, .. , an] and returns another container2 with values [convert(a1), .. , convert(an)]. If container2 is std::vector, the problem is trivial, std::transform does exactly what I want. The following function can deal with arbitrary container2 and container1

template<class ToType, class FromType>
ToType convert(const FromType& from)
{
    std::vector<typename ToType::value_type> tmp;
    std::transform(from.begin(), from.end(),
                   std::back_inserter(tmp),
                   [](const typename FromType::value_type& f) {
        return convert<typename ToType::value_type>(f);
    });
    return ToType(tmp.begin(), tmp.end());
}

但是它会添加副本.有谁知道如何做得更好?

But it does addition copy. Does anyone know how to do better?

查看此答案

Check out this answer to Is it possible to write a C++ template to check for a function's existence?. You can use SFINAE to detect if a function of your destination container exists (such as push_back or insert) or if an inserter for your container exists (such as inserter or back_inserter), and behave accordingly.

另一种方法是创建一个伪造的迭代器:

Another way is to create a fake iterator:

template <class T, class U>
struct ConvertIterator {
    typedef T dest_type;
    typedef U it_type;

    ConvertIterator(U&& val) : iterator(std::forward<U>(val)) {

    }

    bool operator == (const ConvertIterator &other) const {
        return iterator == other.iterator;
    }

    bool operator != (const ConvertIterator &other) const {
        return iterator != other.iterator;
    }

    dest_type operator * () const {
        return convert<dest_type>(*iterator);
    }

    ConvertIterator<T, U> & operator ++() {
        ++iterator;
        return *this;
    }

    it_type iterator;
};

然后:

template<class ToType, class FromType>
ToType convert(const FromType& from)
{
    typedef ConvertIterator<typename ToType::value_type, decltype(from.begin()) > convert_it;

    return ToType(convert_it(from.begin()), convert_it(from.end()));
}