我正在尝试编写具有以下功能的某个类。
在外面,我有一组定义类型和成员函数的类:
class X
{
public:
using energy_t = std::array<double,N>; // N is some number 1,2,3...
energy_t calc_energy(/*params*/);
// everything else
};
我想创建一个类模板,它可以包含这些小类的不同组合并在它们上调用一些功能。energy_t
要求是此类集合中的所有s 都是相同的。这是第一种方法:
template<typename Part, typename... Parts>
requires (std::is_same_v<typename Part::energy_t, typename Parts::energy_t> && ...)
class State
{
public:
static constexpr int degeneracy = std::tuple_size_v<typename Part::energy_t>;
// right now is deduced from given types
using energy_t = std::array<double, degeneracy>;
private:
std::tuple<Part, Parts...> _parts;
public:
State(Part&& part, Parts&&... parts) : _parts(part, parts...) {}
// functionality, usually with std::apply() on _parts tuple member
}
这几乎可以满足所有需求,并且可以使用 CTAD 很好地实例化(这很重要,因为某些参数不是默认可构造的):
State state{X(), Y(/*ctor-params*/), Z()};
问题:目前,唯一检查的是所有energy_t = std::array<double,N>
s 都相同。但是,没有具体说明N
需要什么数量。这将是构造的“完美”语法:
State<3> state{X(), Y(/*params*/), Z()};
// only types with energy_t = std::array<double,3> are accepted
因为它只是一个明确的陈述:State<3>
是一个三重退化状态,{X(), Y(), ...}
其部分是就地构建的。
但是,这似乎是不可能的,因为禁止只指定模板参数的一部分。
想到的一件事就是将另一个模板参数添加到构造函数中并继续执行 CTAD,例如
template<size_t N, typename Part, typename Parts...>
class State
{
State(size_t N, Part&& part, Parts&&... parts) : _parts(part, parts) {};
// etc
};
State state{3, X(), Y()};
还有其他方法可以解决这个问题吗?