gno*_*bal 9 c++ templates variadic-templates c++11
为什么这段代码会编译?(用g ++和clang ++测试)
以下代码用于接受函数并从中创建转发std :: function的工厂方法.如您所见,lambda内部接受const Arg&参数并将它们转发给给定的函数.
在main()我使用factory()创建一个转发器来test_func(),它接受一个非const引用参数.我不明白为什么这不会产生关于从参数中丢弃const限定符的错误.
请注意,实际C创建的类的实例是在main()不创建任何副本的情况下传递的.
#include <functional>
#include <iostream>
class C
{
public:
C() {}
C(const C&)
{
std::cout << "C copy\n";
}
};
int test_func(C& cref)
{
return 0;
}
template<typename Ret, typename... Arg>
std::function<Ret (const Arg&...)> factory(Ret (*func) (Arg...))
{
return [ func ] (const Arg&... arg) -> Ret {
return (func)(arg...);
};
}
int main() {
auto caller = factory(test_func);
C c;
caller(c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如评论中所提到的,您应该使用完美转发(请参阅Scott Meyers关于Universal参考的演示文稿).
在你的情况下,它应该是:
#include <functional>
#include <iostream>
#include <utility>
class C
{
public:
C() {}
C(const C&)
{
std::cout << "C copy\n";
}
};
int test_func(const C& )
{
return 0;
}
template<typename Ret, typename... Arg>
std::function<Ret (Arg...)> factory(Ret (*func) (Arg...))
{
return [ func ] (Arg&&... arg) -> Ret {
return func(std::forward<Arg>(arg)...);
};
}
int main() {
auto caller = factory(test_func);
const C c;
caller(c);
}
Run Code Online (Sandbox Code Playgroud)
请注意我已更改C c;为const C c;您main(),并修改了test_func.
如果要避免创建副本,则必须确保test_func函数不按值获取.它应该通过引用(非const的const).