虽然最初似乎是工作中,但当通过maker函数调用时(为了进行模板参数推导),存在两个重载,一个用于T const&,另一个用于T&& 断点编译:
#include <iostream>
#include <utility>
#include <functional>
using namespace std;
// -----------------------------------------------
template<typename T, typename F>
struct Test
{
T m_resource;
F m_deleter;
Test(T&& resource, F&& deleter)
: m_resource(move(resource)), m_deleter(move(deleter))
{
}
Test(T const& resource, F const& deleter)
: m_resource(resource), m_deleter(deleter)
{
}
};
// -----------------------------------------------
// -----------------------------------------------
template<typename T, typename F>
Test<T, F> test(T&& t, F&& f)
{
return Test<T, F>(move(t), move(f));
}
template<typename T, typename F>
Test<T, F> test(T const& t, F const& f)
{
return Test<T, F>(t, f);
}
// -----------------------------------------------
int main()
{
// construct from temporaries --------------------
Test<int*, function<void(int*)>> t(new int, [](int *k) {}); // OK - constructor
auto tm = test(new int, [](int *k){}); // OK - maker function
// -----------------------------------------------
// construct from l-values -----------------------
int *N = new int(24);
auto F = function<void(int*)>([](int *k){});
Test<int*, function<void(int*)>> tt(N, F); // OK - construction
auto m = test(N, F); // Error - maker function
// -----------------------------------------------
return 0;
}有什么想法吗?
发布于 2014-07-15 10:36:32
template<typename T, typename F>
Test<T, F> test(T&& t, F&& f)
{
return Test<T, F>(move(t), move(f));
}此函数模板有两个参数,它们是通用引用。表单模板类型参数&&的函数模板参数遵循特殊的推导规则:如果参数是lvalue,则模板类型参数被推导为lvalue引用类型。如果参数是rvalue,则推导的类型不是引用。
auto m = test(N, F);int* N和function<void(int*)> F是L值,因此对于上述函数模板,T推导为int*&,F推导为function<void(int*)>&。引用折叠应用,参数T&&变为int*& &&,并折叠为int*& (与F&&类似)。
因此,类模板是用引用类型(T == int*&,F == function<void(int*)>&)实例化的。在类模板中,
Test(T&& resource, F&& deleter)
Test(T const& resource, F const& deleter) 将产生相同的签名,因为int*& &&和int*& const&都折叠为int*&,对于F也是如此。
注意,当参数不是const时,参数int*&的函数比参数int* const&的函数更可取。因此,函数模板
template<typename T, typename F>
Test<T, F> test(T const& t, F const& f)将不会在出现错误的行中使用。一般说来,通用的参考参数是非常贪婪的。
发布于 2014-07-15 10:33:15
template<typename T, typename F>
Test<T, F> test(T&& t, F&& f)
{
return Test<T, F>(move(t), move(f));
}此函数处理lvalue和rvalue。当您调用test(N, F)时,参数是非const l值,因此使用了上面的重载,而不是 test(const T&, const F&) 1。它将类模板实例化为Test<int*&, std::function<void(int*)>&>,这不是您想要的。
您只需要一个maker函数:
template<typename T, typename F>
auto test(T&& t, F&& f)
-> Test<typename std::decay<T>::type, typename std::decay<F>::type>
{
return { std::forward<T>(t), std::forward<F>(f) };
}这将接受任何lvalue和rvalue的组合,它将确保您返回所需的类型,并且它将使用它们的原始值类别完美地将参数转发给Test构造函数。
你应该读/看C++11中的通用引用
https://stackoverflow.com/questions/24755451
复制相似问题