C++ C++;将可调用类型作为模板参数的约束

C++ C++;将可调用类型作为模板参数的约束,c++,scala,templates,C++,Scala,Templates,我正在尝试将以下Scala代码移植到C++: trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B] } 我试过这样的方法: template<template <typename> class F> struct Functor { template <typename A, typename B> static F<B> map(const F&l

我正在尝试将以下Scala代码移植到C++:

trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}
我试过这样的方法:

template<template <typename> class F>
struct Functor {
    template <typename A, typename B>
    static F<B> map(const F<A> &fa, ??? f);  // What's the type of `f`?
};
,否则编译器似乎无法推断出
B
是什么)。解决办法似乎是:

template<template <typename> class F>
struct Functor {
    template <typename A, typename A2B>
    static auto map(const F<A> &fa, A2B f) -> F<decltype(f(fa[0]))>;
};
模板
结构函子{
模板
静态自动映射(常数F&fa,A2B F)->F;
};

但是这看起来很难看,
F
可能并不总是支持方括号操作符(或者就此而言,
::value\u type
)。有没有更好的方法来实现这一点?

使用
std::result\u of\u t
和通用lambdas,您将拥有足够好的调用代码:

template<template <typename> class F>
struct Functor {    
    template <typename A, typename A2B>
    static auto map(const F<A> &fa, A2B f) -> F<std::result_of_t<A2B(A)>>;
};

auto bars = Functor<std::vector>::map(foos, [](const auto& foo) { return foo.toBar(); });

<> p>并且,对于所生成的容器类型,您将无法指定其他模板参数,例如“代码> >分配器< /代码>,除非您为特定容器提供专用的专门化。

< P>这样做的C++方法是定义函数。称之为fmap

然后,希望支持它的客户机将
fmap
作为自由函数重写,其中参数1接受客户机对象,参数2接受从内部类型映射到其他类型的函数

你可以写一个trait来表达“支持fmap”并进行“适当的”类型转换,但这很烦人,不值得“支持fmap”更容易,也同样有用


类似地,对于
fbind
等Scala代码意味着什么?@T.C.例如,如果您有一个列表
nums
(类型为
list[Int]
),其中包含
1、2、3
,以及一个
Functor[list]
,您可以执行
Functor[list].map(nums)(x=>(x+1).toString)并返回一个包含
“2”、“3”、“4”
。它类似于
std::transform
F[\u]
语法基本上意味着
F
是一种可以“包含”另一种类型的类型。您是绑定到C++11还是C++14可用?@AntonSavin C++14可用。可以帮助吗?谢谢!您答案中的最后一句话非常有用!:)
template<template <typename> class F>
struct Functor {    
    template <typename A, typename A2B>
    static auto map(const F<A> &fa, A2B f) -> F<std::result_of_t<A2B(A)>>;
};

auto bars = Functor<std::vector>::map(foos, [](const auto& foo) { return foo.toBar(); });
template<template <typename...> class F>
struct Functor {