【发布时间】:2018-08-16 21:23:13
【问题描述】:
假设您有一个对向量进行操作的类:
class Foo{
public:
Foo() {
m_dynamic_data.push_back(5);
std::cout << m_dynamic_data[0] << std::endl;
}
private:
std::vector<int> m_dynamic_data;
};
在我的例子中,这个类非常庞大,有 2500 行额外的代码。
这个类的行为是动态的(因此std::vector)。但我也想提供一个“静态”实现(使用std::array)。所以添加了std::size_t N,现在应该控制何时使用哪个属性。
template<std::size_t N>
class Foo{
private:
std::vector<int> m_dynamic_data; //use this, when N == 0
std::array<int, N> m_static_data; //use this, when N != 0
};
我不确定我是否可以让它工作。使用 #define 不会完成这项工作(因为它不能交替)。 constexpr 也不能包含两个属性。最好的解决方案可能是提供一个基类,然后从中继承动态和静态案例。但是在我花了接下来的几天做这个之前,我想知道到底有没有技巧。
我考虑将两者都放入std::unique_ptr 并仅构建相关数组:
template<std::size_t N>
class Foo {
public:
Foo() {
if constexpr (N) {
m_static_data_ptr = std::make_unique<std::array<int, N>>();
(*m_static_data_ptr)[0] = 5;
std::cout << (*m_static_data_ptr)[0] << std::endl;
}
else {
m_dynamic_data_ptr = std::make_unique<std::vector<int>>(1);
(*m_dynamic_data_ptr)[0] = 5;
std::cout << (*m_dynamic_data_ptr)[0] << std::endl;
}
}
private:
std::unique_ptr<std::vector<int>> m_dynamic_data_ptr;
std::unique_ptr<std::array<int, N>> m_static_data_ptr;
};
我之前问过这个案例here。但显然这似乎不是一个好方法。 (分片内存,缓存未命中率)。 std::optional 似乎也很有趣,但它使 sizeof(Foo) 超出了我的目标。
最终还有使用void指针:
template<std::size_t N>
class Foo {
public:
Foo() {
if constexpr (N) {
m_data = malloc(sizeof(std::array<int, N>));
(*static_cast<std::array<int, N>*>(m_data))[0] = 5;
std::cout << (*static_cast<std::array<int, N>*>(m_data))[0] << std::endl;
}
else {
m_data = new std::vector<int>;
(*static_cast<std::vector<int>*>(m_data)).push_back(5);
std::cout << (*static_cast<std::vector<int>*>(m_data))[0] << std::endl;
}
}
~Foo() {
delete[] m_data;
}
private:
void* m_data;
};
但这看起来很脏 [...] 因此,目标是在编译时使用任一数组结构。感谢您的任何帮助/建议!
【问题讨论】:
-
根据容器的大小和类型对您的班级进行模板化?
-
您可以使用
union并使用if (N) ...来支持使用向量或数组。 -
但是我不能在
std::array上使用resize(...) -
然后将执行
resize的代码放在if constexpr分支中(不完全确定这是否有效,但您可以这样做) -
@ParadobC2 这可能是因为
malloc实际上并没有创建std::vector对象。您需要使用new std::vector<...>或placement new。