我有这段代码:
#include <iostream>
template <int mult>
struct A {
int v;
A (int p) {
v = p * mult;
}
};
int main (void) {
A<4> a (2); // initialize v = 2 * 4
A<4> b = {2}; // initialize v to 2
std::cout << a.v << " " << b.v << std::endl;
}
我想看到&#34; 8 2&#34;。我得到的是&#34; 8 8&#34;。
我想通过构造函数或其他方法初始化v以避免构造函数。我已经研究过initializer_list或聚合初始化但我还没有找到解决方案。唯一的黑客是创建一个带有虚拟额外参数的新构造函数。
有更好的方法吗?
答案 0 :(得分:0)
您可以保留私有构造函数并使用以不同方式处理其参数的静态方法:
template <int mult>
class A {
int v;
A (int p) {
v = p;
}
public:
static A<mult> constructor1(int p) {
return A<mult>(p);
}
static A<mult> constructor2(int p) {
return A<mult>(p * mult);
}
};
答案 1 :(得分:0)
我发现最好的解决方案是为'int v'创建一个容器类。类似的东西:
#include <iostream>
struct Ac {
int v;
};
template <int mult>
struct A : Ac {
A (Ac p) {
v = p.v;
}
A (int p) {
v = p * mult;
}
};
int main (void) {
A<4> a (2); // initialize v = 2 * 4
A<4> b = (Ac{2}); // initialize v to 2
std::cout << a.v << " " << b.v << std::endl;
}
答案 2 :(得分:0)
首先,您应该更喜欢成员初始化列表在构造函数体中分配,即
A (int p): v(p * mult) {}
其次,如果这是XY problem,我建议您遵循其他答案并更改您的设计。正如DeiDei在评论中所指出的那样,界面现在对外人来说还不清楚。
如果你仍坚持这种设计,你可以继续阅读。
您可以使用以std::initializer_list
为参数的构造函数。当列表初始化对象时,首先考虑这样的构造函数。举个例子:
#include <initializer_list>
template <int mult>
struct A {
int v;
A (int p): v(p * mult) {}
A (std::initializer_list<int> l) : v(*l.begin()) {}
};
缺点是在编译时无法确定std::initializer_list
的大小,因此您必须接受大小大于1或大小为0的列表初始值设定项,这会导致表达式{{中的未定义行为1}}。
当然,您可以进行一些运行时检查,例如,
*l.begin()
但是,您必须承受此检查造成的效率损失。