模板参数演绎/替换失败
C++ - Template argument deduction/substitution failed
我的目标是能够在std::vector上使用算术运算符。考虑下面的例子:
#include <vector>
using namespace std;
template <class S, class T, class U> vector<U> operator+(const vector<S> &a, const vector<T> &b){
vector<U> result;
result.reserve(a.size());
for(int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
int main(int argc, char** argv) {
vector<double> bla;
bla = bla + bla;
return 0;
}
这段代码不能编译,因为编译器不能推断模板参数U(这不是一个MWE,但我试图提供一个有意义的例子)。为什么会这样呢?我知道在这里使用三个模板参数可能没有意义。我的想法是,在类型S和T都使用不同的返回类型提供匹配的"+"实现的情况下,我可以同时处理这两种情况。还是会有歧义的问题?我只是想知道编译器是否应该不能推断u,当然下面的代码工作得很好:
#include <vector>
using namespace std;
template <class S, class T> vector<S> operator+(const vector<S> &a, const vector<T> &b){
vector<S> result;
result.reserve(a.size());
for(int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
int main(int argc, char** argv) {
vector<double> bla;
bla = bla + bla;
return 0;
}
您可以使用通用类型
来完成此操作#include <vector>
#include <type_traits>
using namespace std;
template <class S, class T>
vector<typename std::common_type<S, T>::type> operator+(const vector<S> &a, const vector<T> &b)
{
vector<typename std::common_type<S, T>::type> result;
result.reserve(a.size());
for(unsigned int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
int main() {
vector<double> bla;
bla = bla + bla;
return 0;
}
<<p> 生活例子/strong> 编辑:正如Jarod42所建议的,您还可以使用vector<decltype(a[0] + b[0])>
作为另一种可能的返回类型(它可能与common_type不同)。请记住,后一种方法需要尾随返回类型或std::declval (c++ 11)
的解决方案是好的,我想提供更多的细节,并说明为什么宏A的答案更好。
解决方案1:由于将operator+的返回类型作为第三个形参,因此当显式声明模板形参时,必须指定所有三个形参,如下所示:
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
// declare return type as the 3rd parameter
template <class S, class T, class U> std::vector<U> operator+(const std::vector<S> &a, const std::vector<T> &b){
std::vector<U> result(a.size());
for(int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
int main(int argc, char** argv) {
std::vector<double> bla;
bla.push_back(3.14);
bla.push_back(2.7);
// explicity specify three template parameter
bla = ::operator+<double,double,double>(bla,bla);
// print results
std::ostream_iterator<double> os_it(std::cout," ");
std::copy(bla.begin(),bla.end(),os_it);
std::cout << std::endl;
return 0;
}
输出为:
6.28 5.4
方案2:你可以声明返回类型作为第一个参数,然后我们只需要指定返回类型,其他两个参数由编译器推断。
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
//decalre return type as first template parameter
template <class U, class S, class T> std::vector<U> operator+(const std::vector<S> &a, const std::vector<T> &b){
std::vector<U> result(a.size());
for(int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
int main(int argc, char** argv) {
std::vector<double> bla;
bla.push_back(3.14);
bla.push_back(2.7);
// only explicity specify the return type
bla = ::operator+<double>(bla,bla);
// print results
std::ostream_iterator<double> os_it(std::cout," ");
std::copy(bla.begin(),bla.end(),os_it);
std::cout << std::endl;
return 0;
}
输出为:
6.28 5.4
解决方案3:正如宏a给出的,这比上面两个解决方案更好。我们不必显式地指定返回类型。作为一个完整的示例,我还将可运行的示例代码放在这里:
//Note: This file should be compiled with c++11
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
#include <type_traits> // std::common_type c++11
//using std::common_type
template <class S, class T> std::vector<typename std::common_type<S, T>::type> operator+(const std::vector<S> &a, const std::vector<T> &b){
std::vector<typename std::common_type<S, T>::type> result(a.size());
for(int i = 0; i < a.size();++i){
result[i] = a[i] + b[i];
}
return result;
}
// print results
template <typename T>
void printData(const std::vector<T>& bla) {
std::ostream_iterator<double> os_it(std::cout," ");
std::copy(bla.begin(),bla.end(),os_it);
std::cout << std::endl;
}
int main(int argc, char** argv) {
std::vector<double> dvec;
dvec.push_back(3.14);
dvec.push_back(2.7);
std::vector<int> ivec;
ivec.push_back(1);
ivec.push_back(2);
// we need not to explicity specify template parameter
printData(dvec+dvec);
printData(dvec+ivec);
printData(ivec+ivec);
return 0;
}
输出为:
6.28 5.4
4.14 4.7
2 4
编译器如何推断U
?没有提供任何关于U
的信息。
将其更改为只有S
和T
,并使返回类型依赖于S
和T
之间的某种关系。
。
template<typename S, typename T>
auto operator+(vector<S> const &a, vector<T> const &b) -> vector< foo<S,T> >
标准已经提供了一个基于算术的数组类std::valarray
:
std::valarray<double> bla{2.0, 4.0, 6.0};
bla = bla + bla;
相关文章:
- 模板参数替换失败,并且未完成隐式转换
- 要求子句中不允许哪些替换失败?
- 模板参数推导/替换失败,lambda作为函数指针
- 类模板参数推导失败会导致替换失败
- C++ 带有 decltype 的 SFINAE:替换失败成为错误?
- 折叠表达式模板参数推导/替换失败
- 使用"std::function"和先前推断的模板参数替换失败 - 为什么?
- 模板参数推导/替换失败 C++
- 当Boost ::绑定模板函数时,模板参数扣除/替换失败
- SFINAE使用演绎,但用替换失败
- 为什么代码中的模板参数推导/替换失败?-.
- GCC 模板参数推断/替换失败
- 为什么模板参数推导/替换失败
- 模板模板参数的替换失败
- C++模板参数推导/替换失败
- C++模板参数推导/替换失败:
- 使用类型名参数时,模板参数推导/替换失败
- 有没有办法将模板的替换失败转换为布尔值(真/假)或标签(标准::true_type/标准::false_type)
- 模板参数扣除/替换失败-STD :: find()
- std::tuple_cat替换失败