gpt4 book ai didi

c++ - 推导模板化类参数的模板参数 : const issue

转载 作者:太空狗 更新时间:2023-10-29 20:08:12 25 4
gpt4 key购买 nike

我认为这个问题相当普遍,所以应该有一个已知的解决方案。我想出了一个,但我不是很满意,所以我在这里问一下,希望有人能提供帮助。

假设我有一个函数,其签名是

template<typename T>
void foo(const MyArray<const T>& x);

模板参数中的 const 是为了防止我更改数组内容,因为(出于超出此问题的原因)[] 的访问器( ()MyArray<T> )|始终标记为 const,并返回对 T 的引用(因此,const 确保安全,因为 MyArray<T>::operator[] 返回 T& ,而 MyArray<const T>::operator[] 返回 const T& )。

太棒了。但是,具有不同模板参数的模板是不相关的,因此我无法将引用绑定(bind)到 MyClass<T>引用 MyClass<const T> ,这意味着我不能这样做

MyArray<double> ar(/*blah*/);
foo(ar);

请注意,在没有引用的情况下,上面的代码可以工作提供有一个复制构造函数可以让我创建MyArray<const T>来自 MyArray<T> .但是,我不想删除引用,因为数组构造会发生很多次,而且尽管相对便宜,但它的成本会加起来。

所以问题是:我如何调用 fooMyArray<T>

到目前为止,我唯一的解决方案如下:

MyArray<T> ar(/*blah*/);
foo(reinterpret_cast<MyArray<const T>>(ar));

(实际上,在我的代码中,我将重新解释转换隐藏在一个名称更冗长的内联函数中,但最终结果是一样的)。类(class)MyArray没有 const T 的特化这使得它不可重新解释,所以类型转换应该是“安全的”。但这并不是一个很好的阅读解决方案。另一种方法是复制 foo的签名,要有版本取MyArray<T> ,哪个实现执行转换并调用 const 版本。问题是代码重复(我有很多函数 foo 需要重复)。

也许在 foo 的签名上有一些额外的模板魔法?目标是同时通过 MyArray<T>MyArray<const T> ,同时仍然保持常量正确性(即,如果我不小心更改了函数体中的输入,编译器就会发出声音)。

编辑 1:类 MyArray (其实现不在我的控制之下),具有 const 访问器,因为它存储指针。所以打电话v[3]将修改数组中的值,但不会修改存储在类中的成员(即指针和一些类似智能指针的元数据)。换句话说,对象实际上没有被访问器修改,但数组被修改了。这是语义上的区别。不确定他们为什么朝这个方向发展(我有一个想法,但太长无法解释)。

编辑 2:我接受了两个答案之一(尽管它们有些相似)。我不确定(由于很长一段时间要解释的原因)包装器类在我的情况下是否可行(也许,我必须考虑一下)。我也很困惑,虽然

template<typename T>
void foo(const MyArray<const T>& x);
MyArray<int> a;
foo(a);

不编译,下面编译

void foo(const MyArray<const int>& x);
MyArray<int> a;
foo(a);

备注:MyArray确实提供了带有签名的模板化“复制构造函数”

template<typename S>
MyArray(const MyArray<S>&);

所以它可以创建MyArray<const T>来自 MyArray<T> .我很困惑为什么它在 T 时有效是明确的,而如果T则不是是模板参数。

最佳答案

我会留下来

template<typename T>
void foo(const MyArray<T>&);

并确保用 const T 实例化它(例如在 unitTest 中)。

否则您可以创建一个 View std::span .

类似的东西(取决于 MyArray 提供的其他方法,您可能可以做一个更好的常量 View 。我目前只使用 operator[] ):

template <typename T>
struct MyArrayConstView
{
MyArrayConstView(MyArray<T>& array) : mArray(std::ref(array)) {}
MyArrayConstView(MyArray<const T>& array) : mArray(std::ref(array)) {}

const T& operator[](std::size_t i) {
return std::visit([i](const auto& a) -> const T& { return a[i]; }), mArray);
}

private:
std::variant<std::reference_wrapper<MyArray<T>>,
std::reference_wrapper<MyArray<const T>>> mArray;
};

然后

template <typename T>
void foo(const MyArrayConstView<T>&);

但是你需要明确地调用它,(因为推导不会发生,因为 MyArray<T> 不是 MyArrayConstView )

MyArray<double> ar(/*blah*/);
foo(MyArrayConstView{ar});
foo<double>(ar);

关于c++ - 推导模板化类参数的模板参数 : const issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56368233/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com