在下面的代码中无法找出h1
和h2
之间的区别:
#include <utility>
template <class Func>
struct Holder
{
Holder(Func && func) : m_func(std::forward<Func>(func))
{
}
Func m_func;
};
template <class Func>
auto MakeHolder(Func && func)
{
return Holder<Func>(std::forward<Func>(func));
}
int main()
{
auto func = [](int val) {};
Holder h1 = MakeHolder(func);
Holder<decltype(func)> h2(func);
return 0;
}
为什么h1
编译而h2
不编译? GCC的错误是
prog.cc:25 : 31 : error : cannot bind rvalue reference of type 'main()::<lambda(int)>&&' to lvalue of type 'main()::<lambda(int)>'
25 | Holder<decltype(func)> h2(func);
函数模板参数中的Func
类型与decltype<func>
中的main()
类型不同吗?
答案 0 :(得分:0)
区别在于,Func
的Holder类是用不同的类型实例化的:
h1
,它是main()::<lambda(int)>&
h2
,它是main()::<lambda(int)>
您看到,当您拥有类型T的变量并使用它时,用法的类型与变量的类型不同:T&
而不是T
。但是在decltype()
中,语义是不同的。
无论如何,您可以像这样使代码编译:
#include <utility>
template <class Func>
struct Holder
{
Holder(Func func) : m_func(func) { }
Func m_func;
};
template <class Func>
auto MakeHolder(Func && func)
{
return Holder<Func>(std::forward<Func>(func));
}
int main()
{
auto func = [](int) {};
[[maybe_unused]] Holder h1 = MakeHolder(func);
[[maybe_unused]] Holder<decltype(func)> h2(func);
}
或者,如果您确实需要-在初始化程序列表中使用std::move(func)
。但是-我不确定我是否会保留Func
成员,以保留任意Func
(例如,当它是对可能消失的临时内容的引用或指针时。