简体   繁体   中英

C++ Template Function No Matching Call

I'm trying to provide a generic mapping function over STL containers such as vector and list . Here's my implementation:

#include <functional>
#include <algorithm>


template<class A, class B, template <class> class F>
F<B> fmap(F<A> &functor, std::function<B(A)> &f)
{
  F<B> newFunctor;

  return std::transform(begin(functor)
                , end(functor)
            , begin(newFunctor)     
            , f);
}

But when I try and call it with the code:

vector<int> v;

for(int i = 0; i < 5; i++) {
  v.push_back(i);
}

vector<int> w = fmap(v, [](int i) { return i + 1; });

I get a no matching function call error.

How can I get this to work?

There are a couple of things wrong in the code. The first thing, as already pointed out, is that the std::vector template takes 2 template arguments, the stored type and the allocator. Even though the second is defaulted to be the instantiation of std::allocator with the stored type, it is still an argument to the template.

The second problem you will encounter is that although you can create a std::function from a lambda, the lambda expression is not a std::function , so the compiler will fail to match the second argument.

向量有2个模板参数

template < class T, class Alloc = allocator<T> > class vector; 

You can obtain some independence from the exact declaration structure of the container type by assuming that all applicable container types are template classes whose first parameter is the value type. For output, produce a container with a different value type and all other template parameters the same. This is possible with a type trait that can rebind containers with differing value type:

template <typename Container>
struct container_rebind;

template <template <typename...> class Container, typename ValueType, typename... OtherArgs>
struct container_rebind<Container<ValueType, OtherArgs...>> {
    template <typename NewValueType>
    using rebind = Container<NewValueType, OtherArgs...>;
};

template <typename Container, typename NewValueType>
using ContainerRebind = typename container_rebind<Container>::template rebind<NewValueType>;

so, eg, ContainerRebind<std::vector<int>, double> is std::vector<double> . It's possible to partially specialize container_rebind to support other kinds of container templates, such as those that have non-type template parameters. Adding support for std::array , for example, is left to the reader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM