没有const_cast <>的const更改为什么没有编译器警告/错误?

时间:2018-07-19 05:47:21

标签: c++ const language-lawyer

演示该问题的代码示例:

#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。

3 个答案:

答案 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 *)>的原始签名仍然存在,并且由编译器很好地维护。