Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板元编程帮助:转换向量_C++_Templates_C++11_Template Meta Programming - Fatal编程技术网

C++ 模板元编程帮助:转换向量

C++ 模板元编程帮助:转换向量,c++,templates,c++11,template-meta-programming,C++,Templates,C++11,Template Meta Programming,作为我的第一个模板元程序,我正在尝试编写一个将输入向量转换为输出向量的函数 例如,我想要 vector<int> v={1,2,3}; auto w=v_transform(v,[](int x){return (float)(x*2)}) 问题1:为什么对v\u transform\u的调用不能编译?(它给出了一个无法匹配模板的错误,c++11。我在参数列表中尝试了4种“const”和“&”和“*”的排列,但似乎没有任何帮助。) 我更喜欢v_transform\u doesnet

作为我的第一个模板元程序,我正在尝试编写一个将输入向量转换为输出向量的函数

例如,我想要

vector<int> v={1,2,3};
auto w=v_transform(v,[](int x){return (float)(x*2)})
问题1:为什么对
v\u transform\u的调用不能编译?(它给出了一个无法匹配模板的错误,c++11。我在参数列表中尝试了4种“const”和“&”和“*”的排列,但似乎没有任何帮助。)

我更喜欢
v_transform\u doesnetwork
的实现,而不是
v_transform
的实现,因为它更简单,但有一个小问题,就是不能工作

问题2:为什么调用
v_transform
有效?我明白了发生的事情的要点,但我不明白为什么定义U时需要所有的类型名,我不明白这种奇怪的定义模板参数的语法是如何被允许的,或者在什么地方都被指定了。我试着在cppreference中查找“依赖类型名称”,但对这种语法一无所知


进一步说明:我假设
v_transform
可以工作,因为它可以编译。如果在某些情况下它会失败或出现意外行为,请告诉我。

您的
不工作
需要一个函数指针和模式匹配

lambda不是函数指针。无状态lambda可以转换为函数指针,但模板模式匹配不使用转换(除了非常有限的子集--
派生的&
基的&
派生的*
基的&
,对值的引用,反之亦然,等等--决不是构造函数或转换运算符)

foo
传递给
doesnowork
,它应该可以工作,除非代码中出现打字错误

template<typename T, 
  typename Functor,
  typename U=typename std::result_of<Functor(T)>::type
>
vector<U> v_transform(const std::vector<T> &v, Functor&& f){
  vector<U>ret;
  for(const auto & e:v)
    ret.push_back(f(e));
  return ret;
}

其中包括一些特殊情况。

您的
网络不需要函数指针和模式匹配

lambda不是函数指针。无状态lambda可以转换为函数指针,但模板模式匹配不使用转换(除了非常有限的子集--
派生的&
基的&
派生的*
基的&
,对值的引用,反之亦然,等等--决不是构造函数或转换运算符)

foo
传递给
doesnowork
,它应该可以工作,除非代码中出现打字错误

template<typename T, 
  typename Functor,
  typename U=typename std::result_of<Functor(T)>::type
>
vector<U> v_transform(const std::vector<T> &v, Functor&& f){
  vector<U>ret;
  for(const auto & e:v)
    ret.push_back(f(e));
  return ret;
}

其中包括一些特殊情况。

对于
doesnetwork
函数,您需要明确指定模板参数:

auto zzz=v_transform_doesntwork<int,float>(v,[](const int &x){return (float)(x*2);});
auto zzz=v_transform_doesnetwork(v,[](const int&x){return(float)(x*2);});

然后它就起作用了。编译器无法在将lambda转换为函数指针时隐式确定这些参数。

对于
doesnetwork
函数,需要显式指定模板参数:

auto zzz=v_transform_doesntwork<int,float>(v,[](const int &x){return (float)(x*2);});
auto zzz=v_transform_doesnetwork(v,[](const int&x){return(float)(x*2);});
然后它就起作用了。编译器无法在将lambda转换为函数指针时隐式确定这些参数。

问题1 为什么对
v\u transform\u的调用不能编译

这是因为您向它传递了一个C++11 lambda。
v_transform\u doesnetwork
中的模板参数是函数指针参数。实际上,C++11 lambda是未知类型的对象。那么宣言呢

template<typename T, typename U>
vector<U> v_transform_doesntwork(const std::vector<T> &v, U(*f)(const T &))
同样,
T
是表示输入类型的模板参数。但是现在,
Functor
是您决定传入到
v_transform
的任何可调用对象的参数(名称没有什么特别之处)。我们将
U
设置为等于调用
T
函子的结果。
函数的
std::result_跳过一些环来计算返回值。您还可能希望将
U
的定义更改为

typename U=typename std::result_of<Functor&(T const &)>::type>
typename U=typename std::result\U of::type>
因此,我们可以接受以常量或引用为参数的函数。

问题1 为什么对
v\u transform\u的调用不能编译

这是因为您向它传递了一个C++11 lambda。
v_transform\u doesnetwork
中的模板参数是函数指针参数。实际上,C++11 lambda是未知类型的对象。那么宣言呢

template<typename T, typename U>
vector<U> v_transform_doesntwork(const std::vector<T> &v, U(*f)(const T &))
同样,
T
是表示输入类型的模板参数。但是现在,
Functor
是您决定传入到
v_transform
的任何可调用对象的参数(名称没有什么特别之处)。我们将
U
设置为等于调用
T
函子的结果。
函数的
std::result_跳过一些环来计算返回值。您还可能希望将
U
的定义更改为

typename U=typename std::result_of<Functor&(T const &)>::type>
typename U=typename std::result\U of::type>

因此,我们可以接受以常量或引用为参数的函数。

闭包不是函数指针。它们可以转换为它们,但这不是一回事。那么为什么不转换呢?如果可以依赖C++11,请查看尾部返回类型和
decltype
。它们将使您的生活更加轻松。@kdog:要转换,您需要说明要转换为哪种类型,但您没有这种情况,因为您选择了请求模板参数推断。参数推导还不考虑用户定义的转换(如果您考虑的话,这将永远不会起作用)。闭包不是函数指针。它们可以转换为它们,但这不是一回事。那么为什么不转换呢?如果可以依赖C++11,请查看尾部返回类型和
decltype
。他们会让你的生活更轻松。@k