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