直接或通过构造函数初始化具有相同类型的类

时间:2017-12-09 02:34:58

标签: c++

我有这段代码:

#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或聚合初始化但我还没有找到解决方案。唯一的黑客是创建一个带有虚拟额外参数的新构造函数。

有更好的方法吗?

3 个答案:

答案 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()

但是,您必须承受此检查造成的效率损失。