我有一个模板类foo(本质上是一个矩阵)。 foo的模板参数只能是int
,float
或double
,即不是const int
。这样做的原因是我有专门的运算符,复制const情况的运算符似乎是多余的。我有两个get_data
函数,它们返回一个具有适当const的指针。但我也不是一个选择单行并返回row
的{{1}}函数,这样调用者就无法修改返回的对象。
我的问题:
1)我如何制作B const?
2)我应该为例如foo?
2)我应该制作一个reference_foo类吗?
const foo
为简单起见,省略了操作员功能。
答案 0 :(得分:1)
这里有两种常数。 Const数据和const句柄。
我们想要做的是从四种组合中创造理智:
此外,将返回值标记为const没有意义。返回值是r值。它将被复制或移动。这不会在调用站点产生const句柄。
因此我们需要在get_data()
的2个位置检测常数。 C ++首先为我们做了一个const重载。然后我们必须推迟到另一个模板,该模板在推导的上下文中进行评估,以便我们可以使用std::enable_if
:
#include <cstddef>
#include <utility>
#include <type_traits>
// default getter - element != const element
template<class Element, typename = void>
struct data_getter
{
using element_type = Element;
using const_element_type = std::add_const_t<element_type>;
// detect mutable container
element_type* operator()(element_type ** pp) const
{
return *pp;
}
// detect const container
const_element_type* operator()(element_type * const * pp) const
{
return *pp;
}
};
// specific specialisation for element == const element
template<class Element>
struct data_getter<Element,
std::enable_if_t<
std::is_same<Element, std::add_const_t<Element>>::value>>
{
// in this case the container's constness is unimportant, so
// we use const because it means only writing one method
Element* operator()(Element *const* p) const
{
return *p;
}
};
template <class T>
class foo
{
public:
using element = T;
using const_element = std::add_const_t<element>;
int rows = 0;
int cols = 0;
element * data = nullptr;
bool reference = false;
public:
foo() = default;
//foo(const foo&) // this is not included here for simplicity
//foo& operator=(const foo&) // this is not included here for simplicity
foo(int r, int c) : rows(r), cols(c)
{
data = new element[rows * cols];
}
~foo()
{
if (!reference)
{
delete[] data;
}
}
decltype(auto) get_data()
{
// defer to getter
return data_getter<element>()(&data);
}
decltype(auto) get_data() const
{
// defer to getter
return data_getter<const_element>()(&data);
}
// this will return a mutable container of const data
foo<const_element> row(int r) const
{
foo<const_element> t;
t.rows = 1;
t.cols = cols;
t.reference = true;
t.data = get_data() + r * cols;
return t;
}
};
int main()
{
foo<int> A(2, 1);
A.get_data()[0] = 1;
auto AC = A.row(0);
auto x = AC.get_data()[0]; // fine
// AC.get_data()[0] = 1; // assignment of read-only location
return 0;
}