是“const_cast”在值得保留 API 的参考上“删除 const ”

is `const_cast`ing away const on a reference worth it to preserve the api

提问人:Fantastic Mr Fox 提问时间:9/20/2023 最后编辑:Jan SchultkeFantastic Mr Fox 更新时间:9/20/2023 访问量:117

问:

我们有 GPU 编程范式 sycl 的特定情况,如此修复请求中所述,我们希望使用来自缓冲区的只读访问。具体来说,对用例进行成像,例如:

namespace my_lib {

using buffer_type = sycl::buffer<2>;

void process_image(sycl::queue& queue, const buffer_type& input, buffer_type& output);

}

这是一个合理的接口,传递给所有操作的队列是可变的,输入是常量的,输出不是。但是,由于上面提到的修复请求,这在内部将导致:

void process_image(sycl::queue& queue, const buffer_type& input, buffer_type& output) {
    // ...
    auto input_accessor = input.get_access<sycl::access::read>(cgh);
    // ...
}

这将不可避免地无法编译:

src/gpu_lib/process_image.ipp:112:22: error: no matching member function for call to 'get_access'
                    .get_access<sycl::access::mode::read>(cgh);
                    ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/intel/oneapi/compiler/2023.0.0/linux/bin-llvm/../include/sycl/buffer.hpp:489:3: note: candidate function template not viable: 'this' argument has type 'const sycl::buffer<float, 2, sycl::detail::aligned_allocator<float>, void>', but method is not marked const
  get_access(
  ^

因此,我们来到了一个决策点,我们可以将 API () 设置为非常量,这对用户来说有点骗人,因为它不会被修改。或者,我们用来允许这种行为:buffer_type& inputconst_cast

  sycl::accessor input_acc =
                const_cast<std::remove_cvref_t<decltype(input)>&>(input)
                    .get_access<sycl::access::mode::read>(cgh);

这导致了 2 个任务:

  1. 抛弃这个参考的恒常性安全吗?
  2. 哪个是更好的选择?对此有明确的答案吗?
C++(英语:C++) 常播 SYCL DPC++

评论

0赞 HolyBlackCat 9/20/2023
这个怎么样?将 a 包装在一个类中,为它编写一个 const-correct getter,以及一个忽略 const-correctness 的方法。private: mutable sycl::bufferprocess_image(...) const
1赞 Vivick 9/20/2023
感觉像是 sycl 的库设计问题。有点像 C++20 视图

答:

1赞 alagner 9/20/2023 #1

请定义安全。它容易出现 UB。

github 主题提到 .implementations may modify the state of the buffer even if it is const

我不能为作者说,但这似乎是一个不让它持续的合理理由。我敢说,让函数接受是对用户的更多谎言,因为这与 API 不兼容。const buffer_type&buffer_type

如果函数是常量的,而某些成员是可变的,则是另一回事;如果可能的话,这是一个可以考虑的选择。get_accessbuffer_type

但是为了仅使用 API,我会选择将引用设置为非常量。

评论

3赞 user17732522 9/20/2023
"不,它是UB(未定义行为)“:这完全取决于所引用对象的行为和性质。get_accessconst
0赞 Chris Kushnir 9/20/2023
我认为只有当 orig 对象是 decl const 并且您在抛弃 const 后尝试对对象进行写入时,它才是 ub。 在这种情况下,很明显 (?) 只进行了读取,所以不应该是 UB。
0赞 alagner 9/20/2023
请注意 github 主题:.因此,无论哪种方式,UB都有很大的潜力implementations may modify the state of the buffer even if it is const
0赞 j6t 9/20/2023
你误解了这个概念吗?仅仅因为参数是引用并不意味着它引用的对象是 。如果不是,那么从语言的角度来看没有任何问题。但即使是这样,Sycl 似乎也暗示了根据您的引用定义良好的行为,因为它为实现提供了修改 const 对象的余地。但这与OP的担忧无关。constconst
0赞 alagner 9/20/2023
@j6t编辑的。我可能还不够清楚。
0赞 pptaszni 9/20/2023 #2

抛弃恒常性是安全的,只要

  • 基础对象实际上不是常量
  • 您实际上不会修改底层对象(如果它确实是 const)

所以,在你的情况下,我会说(不是一个明确的答案)你可以保留函数签名,然后在那个地方使用它。围绕为什么需要它发表一些评论。const_cast

另一个值得注意的需要(鼓励)的情况是将特征矩阵的切片传递给函数时。情况与你的情况相反(在这里你实际上想修改绑定到 const ref 的对象),但也许会给你更多的见解。const_cast