C++ const ref类型的函数参数模板参数不明确
将const ref参数传递给调用其他函数的模板函数时出现问题。考虑下面的代码:C++ const ref类型的函数参数模板参数不明确,c++,templates,c++11,forwarding-reference,C++,Templates,C++11,Forwarding Reference,将const ref参数传递给调用其他函数的模板函数时出现问题。考虑下面的代码: struct A { void foo(const int& i) { } }; template <class ...Args> void a_caller(A& a, void(A::*f)(Args...), Args&& ...args) { (a.*f)(std::forward<Args>(args)...); } int m
struct A
{
void foo(const int& i) { }
};
template <class ...Args>
void a_caller(A& a, void(A::*f)(Args...), Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
int main()
{
int i = 42;
A a;
a_caller(a, &A::foo, i); // (1) compiler error
a_caller<const int&>(a, &A::foo, i); // (2) ok
}
我的第一个问题是为什么会发生这种情况?我给编译器一个非重载函数a::foo,为什么它不能从中推断出Args
?
第二个问题是为什么std::make_不具有唯一性?以下代码在我看来是相同的,但编译器在推导构造函数参数类型时没有问题:
struct A
{
A(const int& i) { }
};
int main()
{
int i = 42;
auto aptr = std::make_unique<A>(i);
}
结构A
{
A(常数int&i){}
};
int main()
{
int i=42;
自动aptr=std::使_唯一(i);
}
您试图迫使
Args
履行两个不同(但不一定兼容)的角色。第一个角色是f
的参数类型。第二种是提供给调用方的参数类型
由于完美转发的实现方式,在您的示例中传递i
希望推断此i
的Args
类型为int&
。但是,在A::foo
中相同的Args
类型属于const int&
——因此推断不明确
在某种程度上,完美转发的关键在于,转发参数的类型是当场推导出来的(并且通常不可用于其他任何事情)。所以你必须这样做:
template <class ...Params, class ...Args>
void a_caller(A& a, void(A::*f)(Params...), Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
#include <memory>
struct A
{
void foo(const int& i) { }
};
template <typename F, class ...Args>
void a_caller(A& a, F &&f, Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
int main()
{
int i = 42;
A a;
a_caller(a, &A::foo, i);
}
模板
void a_调用者(a&a,void(a::*f)(参数…,参数和参数)
{
(a.*f)(标准:转发(args)…);
}
当参数与参数不匹配时,您必须依靠调用
f
来通知您。错误消息告诉您发生了什么
see declaration of 'a_caller'
could be 'const int&'
or 'int&'
因此,您正在传递接受const int&
的成员函数,因此编译器将Args
推断为const int&
,但您也将i
传递给Args
,并将其推断为int&
。这些冲突会导致错误。您可以i
编译,也可以传递const int
作为第二个参数
a_caller(a, &A::foo, const_cast<const int&>(i));
const int foo = 42;
a_caller(a, &A::foo, foo);
a_调用者(a,&a::foo,const_cast(i));
常数int foo=42;
a_调用者(a,&a::foo,foo);
我的第一个问题是为什么会发生这种情况?我给编译器一个非重载函数a::foo,为什么它不能从中推断Args
因为您尝试两次推导Args,用于函数a_调用者的第一个和第二个参数。这个推导出的类型不匹配,第一个参数为const int&
,第二个参数为int&
第二个问题是为什么std::make_不具有唯一性
因为make_unique只是将其参数转发给类构造函数
我认为您的代码应该如下所示:
template <class ...Params, class ...Args>
void a_caller(A& a, void(A::*f)(Params...), Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
#include <memory>
struct A
{
void foo(const int& i) { }
};
template <typename F, class ...Args>
void a_caller(A& a, F &&f, Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
int main()
{
int i = 42;
A a;
a_caller(a, &A::foo, i);
}
#包括
结构A
{
void foo(const int&i){}
};
模板
无效a_调用方(a&a、F&F、Args&&…Args)
{
(a.*f)(std::forward感谢使用方法指针作为模板参数的提示-看起来比Angew方案短(对于方法返回类型不重要的情况)