我有下一个代码:
#include <utility>
template<typename T>
struct fun
{
fun(T&&){}
fun(const T&){}
};
template<typename T>
fun<T> create_fun(T&& val)
{
return fun<T>(std::forward<T>(val));
}
template<typename T>
fun<T> create_fun(const T& val)
{
return fun<T>(val);
}
int main()
{
int i = 1;
const int ci = 2;
fun<int> a = create_fun<int>(1);
fun<int> b = create_fun<int>(i);
fun<int> c = create_fun<int>(ci);
fun<int> d = create_fun(1);
fun<int> e = create_fun(i);
//error: no viable conversion from fun<int&> to fun<int>
//why is create_fun(T&& val) a better match than create_fun(const T& val)?
fun<int> f = create_fun(ci);
return 0;
}
你能解释一下为什么对于非常数值,通用引用是更好的匹配吗?
如果没有明确指定a
的类型,我如何才能实现与b
,c
和create_fun
相同的行为?
编辑:
我想强制fun
使用int作为所有3个调用的参数
#include <utility>
template<typename T>
struct fun
{
fun(T&&){}
};
template<typename T>
fun<T> create_fun(T&& val)
{
return fun<T>(std::forward<T>(val));
}
template<typename T>
struct show_type;
int main()
{
int i = 1;
const int ci = 2;
show_type<decltype(create_fun(1))>();
show_type<decltype(create_fun(i))>();
show_type<decltype(create_fun(ci))>();
return 0;
}
答案 0 :(得分:3)
鉴于create_fun(i);
具有非常量左值i
,两个竞争重载的模板参数推断导致:
fun<T> create_fun(T&& val) ==> fun<int&> create_fun(int& val) (T = int &)
fun<T> create_fun(const T& val) ==> fun<int> create_fun(const int& val) (T = int)
第一个是比第二个更好的匹配§13.3.3.2[over.ics.rank] /3.1.6。所以第一个被选中。
您可以只使用一个通用参考模板,而不是使用两个重载,并从const
的返回类型中移除T
中的引用和create_fun
:
template<typename T>
using remove_cv_and_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<typename T>
fun<remove_cv_and_ref_t<T>> create_fun(T&& val)
{
return fun<remove_cv_and_ref_t<T>>(std::forward<T>(val));
}