演示该问题的代码示例:
#include <functional>
#include <set>
void useCallback(std::function<void(char *)> callback)
{
}
int main()
{
std::function<void(char const *)> callback = [](char const *)
{
};
useCallback(callback);
return 0;
}
是的,const
删除在一天结束时是无害的,useCallback()
在其API中声明已准备好接受并使用修改其参数的回调,因此它将执行只需使用没有的功能即可。
那为什么阻止将std::set<char *>
传递给期望std::set<char const *>
的函数的参数在这里不适用?该论点正确地指出char *
和char const *
是不同的类型,因此这两个集合在类型上不是等效的。
牢记这一点,为什么不认为callback
的类型和useCallback()
的参数不同?
-编辑-
这是使用MSVC VS 2017。
答案 0 :(得分:9)
该论点正确地指出
char *
和char const *
是不同的类型,因此这两个集合在类型上并不等效。
std::function<void(char *)>
和std::function<void(char const *)>
也是不同的类型,因此两个功能对象的类型也不相同。只是与std::set
不同,它们不需要等同于类型!
std::function<void(char *)>
具有一个构造函数,该构造函数将接受可以用char *
参数调用的任何对象。可以使用std::function<void(char const *)>
参数来调用char *
,所以很好。从lambda初始化std::function<T>
时使用的是同一构造函数:类型也有所不同,但是只要在T
中传递参数类型时可以调用lambda,就可以接受
答案 1 :(得分:5)
这里没有问题。实际上const
并没有被丢弃,因为使用适合std::function<void(char const *)>
的参数(即提供std::function<void(char *)>
参数)调用char *
函数是完美的。错误的情况将是相反的情况:
void useCallback(std::function<void(char const *)> callback)
{
}
int main()
{
std::function<void(char *)> callback = [](char *)
{
};
useCallback(callback);
return 0;
}
std::function<void(char *)>
不能使用适合std::function<void(char const *)>
调用的参数来调用。因此std::function<void(char const *)>
函数对象的构造函数应该产生错误。
答案 2 :(得分:1)
现有的答案很好地解释了为什么这样做完全合法以及与std::set
参数的区别是什么,我想举一个示例说明类型安全性不会丢失。考虑一下
void useCallback(std::function<void(char *)> callback)
{
callback("abc");
}
这将编译,尽管它会将字符串文字转换为const char*
,这会给您使用clang和gcc的适当警告。无法编译:
void useCallback(std::function<void(char *)> callback)
{
const char *str = "abc";
callback(str);
}
std::function<void(char const *)>
的原始签名仍然存在,并且由编译器很好地维护。