常量正确性建议

3

我有一个接收常量引用的函数,并且我需要使用这个引用调用一个模板库函数:

std::vector<cv::Size> get_resolutions(const rs2::device& dev)
{
    auto sensor = dev.first<rs2::depth_sensor>();

    //more code    
}


class device
{
public:

    template<class T>
    T first()
    {
        for (auto&& s : query_sensors())
        {
            if (auto t = s.as<T>()) return t;
        }
        throw rs2::error("Could not find requested sensor type!");
    }

    //more code

};

当我使用gcc编译时,我会得到以下错误:

错误:将“const rs2 :: device”作为“this”参数传递会丢弃限定符[-fpermissive]

我不能更改first()函数,因为它是外部库(librealsense)的一部分(第51行here)。 我不能从函数参数dev中删除const,因为这会导致在许多地方移除常量正确性。

我可以通过从dev中删除const来克服错误:

auto sensor = const_cast<rs2::device&>(dev).first<rs2::depth_sensor>();

然而,这种做法并不好。是否有更正确的方法来处理此错误?我尝试了以下变化但都没有成功:
auto sensor = dev.first<const rs2::depth_sensor>();
auto sensor = const_cast<const rs2::depth_sensor>(dev.first<rs2::depth_sensor>());

但是我使用它们时也出现了相同的错误。


将这个 rs2::device 对象放入一个 std::shared_ptr(或者可能是 unique_ptr)中,将其存储在包装对象内,并使您的包装对象成为其外观。指定您的外观方法的 const-ness,以便将其转发到 rs2::device 方法。您的外观的 template<class T> T first() const 将没有问题解引用包装的 const std::shared_ptr,然后调用包装对象中的真实方法。 - Sam Varshavchik
2
最好的做法是删除您认为是常量正确性的部分 - 因为它是一个库函数;而且你不知道 first 是否会改变对象。常量正确性的整个重点在于它必须是...正确的 ;) - UKMonkey
你可以询问开发人员实际意图是什么。很可能只是缺少 const,因为唯一的其他可能修改操作是调用 query_sensors,但它本身是 const。如果是这种情况,请立即使用 const_cast,因为将来可能会进行适应,但您确定此转换永远不会导致 UB。但如果这是意图,请像 @UKMonkey 所说的那样或将函数拆分为 constmutable 部分。 - Jodocus
我认为这个lib函数应该是“const”的。你可以fork它并添加“const”。 - M.M
1个回答

4
我认为有两种可能的解决方案。要么允许get_resolutions通过非const引用来获取dev(尽管这可能需要您修改调用代码),要么自己重新实现first

选项1

只需替换

std::vector<cv::Size> get_resolutions(const rs2::device& dev)

使用

std::vector<cv::Size> get_resolutions(rs2::device& dev)

然而,这也意味着您不能再使用临时对象调用get_resolutions

选项2

然而,查看库的源代码,我确实看不出为什么first()是非const的。它所做的就是调用query_sensors()(它是const限定的,并且也是公共的),并处理结果:1

template<class T>
T first()
{
    for (auto&& s : query_sensors())
    {
        if (auto t = s.as<T>()) return t;
    }
    throw rs2::error("Could not find requested sensor type!");
}

这可能是影响最小的选项:只需在库外自定义一个first(),以复制此功能:
template <class T>
T custom_first(const rs2::device& dev)
{
    for (auto&& s : dev.query_sensors())
        if (auto t = s.as<T>())
            return t;
    throw rs2::error("Could not find requested sensor type!");
}

1 是时候提交一个错误报告了,也许?


我将在librealsense项目中开一个问题,并临时使用custom_first()函数。 - martinako

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接