假设我们有一个原始的C风格字符串"test"
。我们可以声明一个这样的函数:
void printText(std::string textToPrint){
std::cout << textToPrint << "\n";
}
我们可以通过以下方式调用它:
printText("test");
这应该是完全正常的,因为参数是一个对象,而不是一个引用,因此应该在调用函数`printText()'时创建像std::string("test")
这样的临时对象。
现在,我有一个以下模板:
template <typename T>
T checkMe(Proxy<T> arg){
std::cout << arg() << std::endl;
return arg();
}
其中Proxy
类声明如下:
template <typename T>
class Proxy{
public:
Proxy(std::function<T&()> caller);
Proxy(std::shared_ptr<T> dataPtr);
T& operator()();
private:
std::function<T&()> m_functional;
std::shared_ptr<T> m_data;
};
它的目的是使用两种对象类型调用一些函数:
一个是数据的shared_ptr
,另一个是功能对象,它返回这种类型的数据。
现在,当我想调用函数checkMe
时,会发生错误,我不知道为什么会出现以及如何解决它。一件事是:
getMe(std::make_shared<int>(255));
这在我看来应该完全正常,因为Proxy的构造函数将shared_ptr作为参数并基于它创建自己。但这会给编译器的演绎错误。然而,当我调用这样的函数时:
getMe<int>(std::make_shared<int>(255));
现在好了。我不知道为什么编译器不能自己推断出类型。
第二种情况是用功能对象调用它:
getMe<int>(std::bind(getNumberMult,5,6));
getNumberMult
的定义如下:
int xy;
int& getNumberMult(int x, int y){
return xy = x*y;
}
此处发生转换错误。有人可以指定是否可能以及如何实现给定代码的期望行为并解释我对该机制的理解有什么问题?我想使用以下代码:
getMe(std::make_shared<int>(300));
getMe(std::bind(getNumberMult, 6, 7));
编译器错误:
使用时
getMe<int>(std::bind(getNumberMult, 5, 6));
path/to/file:36: error: C2664: 'T getMe<int>(DataProxy<T>)' : cannot convert argument 1 from 'std::_Bind<true,int &,int &(__cdecl *const )(int,int),int,int>' to 'DataProxy<int>'
with
[
T=int
]
答案 0 :(得分:2)
使用T checkMe(Proxy<T> arg)
,arg
应为Proxy<T>
(或从中继承)。
编译器没有检查测试每个Proxy<T>
可以从给定参数构造的无限可能性。
答案 1 :(得分:0)
所以我现在知道为什么会这样,我该怎么做才能解决它。
考虑以下对象:
struct Test{
Test(std::string someString){}
};
所以我们需要std :: string来构造这个类的对象。
我们可以通过以下方式明确创建std::string
:
int main(){
Test someVariable("someRawString");
}
它会起作用而且完全没问题。发动机罩发生了什么:
Test
类std::string
的临时对象并将此临时对象传递给构造函数现在让我们考虑一下功能:
void someTestFunction(Test someTest){}
它需要Test
类型的对象,它由std::string
鉴于此,以下列方式调用此函数应该没问题:
someTestFunction("someRawText");
但它并不好。这给了我们转换参数的错误。原因很简单:当将参数传递给函数时,C ++只允许转换一步。所以编译器可以:
std::string
Test
std::string
个对象
但它不能:
std::string
std::string
投放到Test
(转化次数过多)给定代码发生了完全相同的事情。为了使它工作,我们应该使用:
getMe<int>(std::make_shared<int>(300));
getMe<int>(std::function<int&()>(std::bind(getNumberMult, 6, 7)));
为什么会这样?
std::make_shared<int>
的返回类型为std::shared_ptr<int>
,因此无需转换即可调用函数。
std::bind...
的返回类型与std::function
不同,它有自己的实现定义的返回类型。这就是为什么这里需要第二次演员,这是C ++不允许的。当我们明确地转换它时,只需要一个隐式转换,一切正常。