有条件地实例化具有已删除的默认构造函数的类

时间:2017-02-16 22:53:29

标签: c++ scope instantiation

考虑一个带有删除的默认构造函数的类(我的实际类更加复杂,并且由于其中一个成员具有已删除的默认构造函数而隐式删除默认构造函数)。我想根据一些输入的值,使用其构造函数实例化我的类,然后做一些事情"。 以下代码显示了由于代码注释中所述的原因而无法完成的两种方式,但会让我了解我想要实现的目标。

#include <vector>
class A {
    bool m_with_v;
    int m_i;
    std::vector<double> m_v;
public:
    A() = delete;
    A(int i) : m_i(i), m_with_v(false) {}
    A(int i, std::vector<double> v) : m_i(i), m_v(v), m_with_v(true) {}
    auto do_stuff() { /* do stuff depending on m_with_v */ };
};

int main(int argc, char* argv[])
{
    bool yes_no;
    /* Obtain a value for yes_no from argv */

    A a; // the default constructor of "A" cannot be referenced -- it is a deleted function
    if (yes_no)
        a = A(1);
    else {
        std::vector<double> v{ 1,2,3 };
        a = A(1, v);
    }
    a.do_stuff();
    // do a bunch more things

    if (yes_no)
        A b(1);
    else {
        std::vector<double> v{ 1,2,3 };
        A b(1, v);
    }
    b.do_stuff(); // identifier "b" is undefined, i.e. it's gone out of scope
    // do a bunch more things
}

这样做的一个显而易见的方法是移动&#34;一堆东西&#34;在if块的每个部分内部,但这会导致很多重复的代码,我想避免这些。

另一个显而易见的方法是创建一个函数来完成&#34;一堆事物&#34;并在if块的每个部分调用它,但是这需要一定量的重构,如果需要传递大量的变量,函数调用可能变得相当丑陋。

所以,我的问题是:有没有办法有条件地实例化我的课程并让它在周围范围内可用?

4 个答案:

答案 0 :(得分:4)

您可以使用条件运算符实例化它:

A a = yes_no ? A(1) : A(1, {1,2,3});
a.do_stuff();

等等。

答案 1 :(得分:2)

auto a = [&]{
    if (yes_no) {
        return A(1);
    } else {
        std::vector<double> v{ 1,2,3 };
        return A(1, v);
    }
}();
a.do_stuff();

答案 2 :(得分:0)

你可以创建一个自由函数(可能是静态的A ::,R Sahu赞成一个自由函数)返回一个合适的函数。

A a = buildA(yes_no);

buildA将是

A buildA(bool yes_no){
   if (yes_no) 
       return A(1);

等等。

答案 3 :(得分:0)

您可以考虑在此使用unique_ptr<A>。这样,您可以推迟实际的对象创建,并在您需要的条件块中创建适当的实例。 例如:

std::unique_ptr<A> ptrA;
if (yes_no)
{
    ptrA.reset(new A(1));
}
else
{
    ptrA.reset(new A(1,{1,2,3}));
}

根据您使用的c ++的实际版本,您可能希望使用std::make_unique而不是reset方法(自C ++ 14以来可用)。在这种情况下,您可以放置​​ptrA = std::make_unique<A>(1);

另一种选择是使用三元运算符A a = (yes_no) ? A(1) : A(1, {1, 2, 3})

或者像其他人建议的那样,将对象创建逻辑提取到一个单独的函数,您可以根据if条件的实现从yes_no块返回对象。