在下面的简化代码中,我尝试这样的事情:
struct A{};
struct B : public A {};
void func(A &a) {}
B b;
func(b);
通常这是有效的,但在下面更复杂的代码中它不起作用。 我想我在模板上遗漏了一些东西。
为什么无法从DenseVector<container_reference<std::array<double, 25ull>>>
转发到container_reference<std::array<double, 25ull> >&
?
#include <iostream>
#include <vector>
#include <array>
#include <cassert>
using namespace std;
template<class C>
struct container_reference
{
typedef typename C::iterator iterator;
container_reference(iterator f, iterator e) : f(f), e(e) {}
void swap(container_reference &c) { std::swap(*f, *(c.f)); /*...and more*/ }
iterator f,e;
};
template<typename C>
struct DenseVector : public C { using C::C; };
template<typename C>
struct DenseMatrixRect
{
typedef DenseVector<container_reference<C>> row_vector;
row_vector row(unsigned int i)
{
auto it = container.begin() + i * width;
return row_vector(it, it + width);
}
C container;
unsigned int width;
};
int main()
{
DenseMatrixRect<std::array<double, 25>> m; m.width = 5;
m.row(0).swap(m.row(1));
return 0;
}
答案 0 :(得分:3)
您的代码失败是因为您尝试将来自container_reference
的临时 row
绑定到swap
。
您只是忘记绑定const
引用并标记方法本身const
:
void swap(const container_reference &c) const { std::swap(*f, *(c.f)); /*...and more*/ }
// ^^^^^ ^^^^^
由于您只交换c
而非c
本身的(非常量)内容,因此您不需要它可以修改。虽然,值得指出的是,这是一个非常不寻常的swap
,其中两个参数都是const
,因为它们只是交换的实际内容的占位符。
答案 1 :(得分:1)
给它起一个名字,然后它就是一个左值,并且演员会工作:
auto x = m.row(1);
m.row(0).swap(x);
另一个选择是添加一个临时版本的交换版本:
void swap(container_reference &&c) { std::swap(*f, *(c.f)); /*...and more*/ }