C++模板允许丢弃常量引用限定符
C++ template allows discard of const reference qualifier
为什么编译这段代码?(用g++和clang++测试)
以下代码适用于接受函数并从中创建转发 std::function 的工厂方法。如您所见,内部的 lambda 接受const Arg&
参数并将它们转发给给定函数。
main()
我使用 factory()
创建一个转发器到 test_func()
,它接受一个非常量引用参数。我不明白的是为什么这不会产生关于从参数中丢弃 const 限定符的错误。
请注意,实际上,在main()
中创建的类C
的实例是在不创建任何副本的情况下传递的。
#include <functional>
#include <iostream>
class C
{
public:
C() {}
C(const C&)
{
std::cout << "C copyn";
}
};
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;
}
正如评论中提到的,你应该使用完美的转发(参见Scott Meyers关于通用参考的演讲)。
在您的情况下,它应该是:
#include <functional>
#include <iostream>
#include <utility>
class C
{
public:
C() {}
C(const C&)
{
std::cout << "C copyn";
}
};
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);
}
请注意,我在您的main()
中将C c;
更改为const C c;
,并修改了test_func。
如果要避免创建副本,则必须确保test_func函数不按值获取。它应该通过引用(非常量常量)。
相关文章:
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 为什么我可以通过引用修改常量返回
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 将常量指针引用绑定到非常量指针
- 通过常量引用传递参数的矩阵模板类
- 按值捕获引用时出现非常量
- 在C++中使用非常量引用作为常量
- 具有常量引用参数的函数模板专用化
- 多个"常量引用"变量可以共享同一个内存吗?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 为什么按值传递QStringView比引用常量更快?
- 通过引用常量函数调用另一个类的非常量函数
- 构造常量对象与引用常量对象
- 引用“常量value_type”时出错
- 为什么可以在 for 语句中重新分配引用常量
- 程序反馈:命名循环索引和引用常量数据
- 堆还是栈?在c++中函数调用中引用常量字符串时
- 为什么常量结构数组在按名称引用常量结构时不放在 .rodata 中?
- 为什么编译器允许在函数中发送对迭代器的引用,该函数引用常量迭代器