提问人:Fantastic Mr Fox 提问时间:9/20/2023 最后编辑:Jan SchultkeFantastic Mr Fox 更新时间:9/20/2023 访问量:117
是“const_cast”在值得保留 API 的参考上“删除 const ”
is `const_cast`ing away const on a reference worth it to preserve the api
问:
我们有 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& input
const_cast
sycl::accessor input_acc =
const_cast<std::remove_cvref_t<decltype(input)>&>(input)
.get_access<sycl::access::mode::read>(cgh);
这导致了 2 个任务:
- 抛弃这个参考的恒常性安全吗?
- 哪个是更好的选择?对此有明确的答案吗?
答:
请定义安全。它容易出现 UB。
github 主题提到 .implementations may modify the state of the buffer even if it is const
我不能为作者说,但这似乎是一个不让它持续的合理理由。我敢说,让函数接受是对用户的更多谎言,因为这与 API 不兼容。const buffer_type&
buffer_type
如果函数是常量的,而某些成员是可变的,则是另一回事;如果可能的话,这是一个可以考虑的选择。get_access
buffer_type
但是为了仅使用 API,我会选择将引用设置为非常量。
评论
get_access
const
implementations may modify the state of the buffer even if it is const
const
const
抛弃恒常性是安全的,只要
- 基础对象实际上不是常量
- 您实际上不会修改底层对象(如果它确实是 const)
所以,在你的情况下,我会说(不是一个明确的答案)你可以保留函数签名,然后在那个地方使用它。围绕为什么需要它发表一些评论。const_cast
另一个值得注意的需要(鼓励)的情况是将特征矩阵的切片传递给函数时。情况与你的情况相反(在这里你实际上想修改绑定到 const ref 的对象),但也许会给你更多的见解。const_cast
评论
private: mutable sycl::buffer
process_image(...) const