В следующем упрощенном коде я пытаюсь что-то вроде этого:
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;
}
Ваш код не работает, потому что вы пытаетесь связать временный container_reference
вернулся из row
в вашем звонке swap
,
Вы просто забыли связать const
ссылаться и отмечать сам метод const
:
void swap(const container_reference &c) const { std::swap(*f, *(c.f)); /*...and more*/ }
// ^^^^^ ^^^^^
Поскольку вы меняете только (неконстантный) контент c
и не c
само по себе, вам не нужно, чтобы это было изменяемым. Хотя стоит отметить, что это довольно необычно swap
где оба аргумента const
потому что они только заполнители для реального контента, который поменялся местами.
Дайте ему имя, тогда это lvalue и актерский состав:
auto x = m.row(1);
m.row(0).swap(x);
Другой вариант — добавить версию подкачки, которая принимает временные значения:
void swap(container_reference &&c) { std::swap(*f, *(c.f)); /*...and more*/ }