C++ 允许一个std::函数类型接受具有不同签名的lambda吗

C++ 允许一个std::函数类型接受具有不同签名的lambda吗,c++,c++11,std-function,C++,C++11,Std Function,我有一个更高阶的函数map,它类似于STLfor_each,并将std::function对象映射到事物的向量上 template<class T, class U> vector<U> map(function<U (T)> f, vector<T> xs) { vector<U> ret; for (auto &x: xs) ret.push_back(f(x)); return ret; } ---编

我有一个更高阶的函数
map
,它类似于STL
for_each
,并将
std::function
对象映射到事物的
向量上

template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
  vector<U> ret;
  for (auto &x: xs)
    ret.push_back(f(x));
  return ret;
}
---编辑---

我特别感兴趣的是
deref
类函数或元函数,它可以从
std::function
对象的类型签名中删除const ref,这样我至少可以自动执行
Q2

我知道,正如@Brian和@Manu正确指出的那样,使用
std::function
来指定类型是不传统的,但我想知道我上面问的问题是否可行。就个人而言,考虑到C#中如何使用泛型函数类型
Func
,我认为使用
std::function
的代码更清晰。如果类型擦除的成本是可以容忍的,那么这是可以接受的


<>我完全同意C++可以推断返回类型,并且在类型错误时给出错误消息。也许这只是一个品味的问题,我更愿意在编写函数签名时把它解释清楚。

惯用的解决方案是简单地允许
map
采用任意函数,比如类型

template<class T, class F>
auto map(F f, vector<T> xs) -> vector<typename result_of<F(T)>::type> {
  vector<typename result_of<F(T)>::type> ret;
  for (auto &x: xs)
    ret.push_back(f(x));
  return ret;
}
模板
自动映射(F,向量xs)->向量{
向量ret;
用于(自动&x:xs)
后推(f(x));
返回ret;
}
这种方法的主要问题是,如果
F
不能用类型为
T
的参数调用,或者如果它返回一些奇怪的信息,例如
void
,则会收到令人困惑的错误消息

(第二个问题是,
map
的第一个参数不能是重载函数;编译器不能简单地选择采用
t
类型参数的重载)


(您可能还想考虑返回< <代码> f>代码> >)

我理解您为什么使用<代码> STD::函数< /> >:您必须知道转换的返回类型来创建向量,对吗?p> 但是考虑一个完全不同的方法。给定
的元函数
std::result\u,您可以计算函数调用的结果类型,因此只需编写:

template<typename F , typename CONTAINER , typename T = typename std::result_of<F(typename CONTAINER::value_type)>::type>
std::vector<T> map( F f , CONTAINER&& container )
{
    std::vector<T> result;

    for( auto& e : container )
        result.emplace_back( f( e ) );

    return result;
}
其中,
std_function
是一个元函数,给定函数类型
F
返回签名为
F
std::function
实例。我把它留给读者作为一个游戏/挑战

就这些。使用make-like功能对其进行改进:

template<typename F , typename... Fs>
overloaded_function<F,Fs...> make_overloaded_function( F&& f , Fs&&... fs )
{
    return { std::forward<F>( f ) , std::forward<Fs>( fs )... };
}
编辑:“谢谢。但是,我真正想要的是一个元函数,它接受可调用函数的签名,并从签名中删除常量引用。” 好的,让我试试:
std::decay
元函数将在按值传递参数时执行的衰减应用于给定类型。这包括删除cv限定符、删除引用等。因此,像您这样的元函数可能采用函数签名类型并将衰减应用于其所有参数:

template<typename F>
struct function_decay;

template<typename R typename... ARGS>
struct function_decay<R(ARGS...)>
{
    using type = R(typename std::decay<ARGS>::type...);
};
模板
结构功能衰减;
模板
结构函数
{
使用type=R(typename std::decay::type…);
};
那就行了

我写这篇文章是因为您在评论中明确要求,但我强烈建议您使用我最初向您展示的替代方案,因为与您的方式相比,它有许多优势。

也就是说,我希望这个答案有助于解决你的问题

不要将
std::function
用作
map
函数参数。只使用一个模板。这减少了您正在试验的耦合,也提高了性能,允许编译器进行内联操作。注意,他有时需要可变的输入,所以我会将
const CONTAINER&
更改为
CONTAINER&
。同时将
F
作为
F&&
,不是为了转发,而是作为一个完美的参考。@Manu343726谢谢。但是,我真正想要的是一个元函数,它接受可调用函数的签名,并从签名中删除常量refs。这是OP中的“deref”部分。@Manu343726谢谢你的建议,我会记住的。我将尝试使用你的
函数
meta\u函数,并计算出练习的
std\u函数
部分。@Manu343726你能发布一下
std\u函数
应该是什么样子吗?
template<typename F , typename... Fs>
overloaded_function<F,Fs...> make_overloaded_function( F&& f , Fs&&... fs )
{
    return { std::forward<F>( f ) , std::forward<Fs>( fs )... };
}
auto f = make_overloaded_function( [](){ return 1; } ,
                                   [](int,int){ return 2; } ,
                                   [](const char*){ return 3; } );

f();        //Returns 1
f(1,2);     //Returns 2
f("hello"); //Returns 3
template<typename F>
struct function_decay;

template<typename R typename... ARGS>
struct function_decay<R(ARGS...)>
{
    using type = R(typename std::decay<ARGS>::type...);
};