转换运算符不适用于函数参数
Conversion operator is not working for function parameter
为什么这段代码不编译?
#include <iostream>
#include <vector>
template<class T>
class vector_ref
{
public:
vector_ref(T *pData, int pN) {Data = pData; N = pN;};
T *Data;
int N;
vector_ref<T>& operator=(const std::vector<T> &v1)
{
for(int ii = 0; ii < N; ii++)
{
Data[ii] = v1[ii];
}
return *this;
};
operator std::vector<T>()
{
std::vector<T> v1(N);
for(int ii = 0; ii < N; ii++)
{
v1[ii] = Data[ii];
}
return v1;
};
};
template<class T>
void printVec(std::vector<T> v1)
{
for(int ii = 0; ii < v1.size(); ii++)
{
std::cout << v1[ii] << std::endl;
}
}
int main()
{
std::vector<double> v;
v.push_back(1.0);
v.push_back(2.0);
v.push_back(3.0);
vector_ref<double> v_ref(&v[0],3);
printVec(v_ref); // Compiler error
return 0;
}
我正在使用以下命令编译g++ 4.7.3
:g++ test.cpp
.错误消息是:
test.cpp: In function ‘int main()’:
test.cpp:56:19: error: no matching function for call to ‘printVec(vector_ref<double>&)’
test.cpp:56:19: note: candidate is:
test.cpp:40:6: note: template<class T> void printVec(std::vector<T>)
test.cpp:40:6: note: template argument deduction/substitution failed:
test.cpp:56:19: note: ‘vector_ref<double>’ is not derived from ‘std::vector<T>’
对前一个问题的回答似乎表明这应该有效。
正如错误消息所说:
test.cpp:56:19: error: no matching function for call to ‘printVec(vector_ref<double>&)’
果然,那句台词是:
vector_ref<double> v_ref(&v[0],3);
printVec(v_ref); // Compiler error
请注意,v_ref
是一个vector_ref<double>
。 现在,错误消息有助于指出有一个printVec
函数,但它是不同的:
test.cpp:56:19: note: candidate is:
test.cpp:40:6: note: template<class T> void printVec(std::vector<T>)
如果我们转到第 40 行并查看 printVec 函数,您将看到:
template<class T>
void printVec(std::vector<T> v1)
所以,这意味着:
- printVec 以
std::vector<T>
为论据。 - 你用
vector_ref<double>
作为参数来调用它。 - 这些是完全不同的类型,所以它失败了。
这就是错误消息的含义。
现在,我看到您正在尝试制作可以隐式转换为向量的东西。 由于模板的原因,这变得混乱。 此方法适用于包装非模板类型,但模板存在问题,原因如下:
当编译器试图处理printVec(v_ref)
时,它必须找到这样一个printVec
的声明。 它寻找需要vector_ref<double>
的东西,但什么也找不到。 它确实找到了一个模板函数,因此它会尝试查看是否可以为此类型实例化模板函数。 printVec
的标志是它需要std::vector<T>
,这与vector_ref<double>
不匹配,所以它不匹配,它继续前进。 真的就像"不匹配,放弃并继续前进"一样简单。 它不会尝试对您的类型进行任何转换。
要解决此问题,您可以按照塞巴斯蒂安的建议添加一个显式.toVector()
。 或者,显式实例化模板方法可能会起作用:
template<class T>
void printVec(std::vector<T> v1)
{
for(int ii = 0; ii < v1.size(); ii++)
{
std::cout << v1[ii] << std::endl;
}
}
template<> void printVec(std::vector<double> v1); // explicit instantiation
这明确地告诉编译器实例化std::vector<double>
的模板方法,然后当它试图找到printVec(vector_ref<double>)
的匹配项时,它将看到两个选项 - 模板方法和实例化方法。 模板方法将像以前一样失败,但它可能会意识到它可以执行隐式转换以使用实例化方法。 这可能有效,但我还没有测试过。
我不确定这是否有效,.toVector()
绝对更干净。 但是显式模板实例化是一个巧妙的技巧,偶尔有用,所以我想我会提到它。
你隐式转换为vector&是不安全的,会做可怕的事情。删除它。并打开编译器警告,因为编译器应该已经为此对你尖叫了。
编译器错误背后的问题是参数推导不考虑转换;它在参数类型和参数类型模式之间执行严格的模式匹配。而且vector<T>
和vector_ref<double>
之间没有匹配.
你没有办法让这条线工作。要么给vector_ref
一个向量的完整接口,printVec
做一个完整的模板,要么使用显式强制转换或显式转换函数,例如 v_ref.to_vector()
.
参见 Sebastian Redl & Tim 的答案,了解为什么编译失败
你可以重载()
:类似于塞巴斯蒂安·雷德尔建议的to_vector
函数
std::vector<T> operator() ()
{
std::vector<T> v1(N);
for(int ii = 0; ii < N; ii++)
{
v1[ii] = Data[ii];
}
return v1;
}
然后使用
printVec(v_ref());
看这里
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数