Условно удалить член класса во время выполнения или пропустить вызывающий конструктор этого объекта-члена. - PullRequest
0 голосов
/ 16 января 2020
// globally accessible variable. can be changed at runtime.
bool feature_flag = true

Class A
{
  UtilityClass obj_util;

  A(int x,int y,int z)
  {
  }
}

Class UtilityClass
{
  UtilityClass()
  {
  }
}

Main()
{
  A a(10,20,30);
}

Когда создается объект для A, он создает экземпляр объекта UtilityClass внутри A и поэтому вызывает конструктор UtilityClass ().

Мой новый сценарий и проблема:

когда feature_flag активирован (true), некоторые компоненты не будут доступны в UtilityClass (не спрашивайте меня, как), поэтому вызов конструктора UtilityClass () не будет выполнен.

Чтобы избежать этой ошибки,

1 ) Я хочу, чтобы член obj_util был удален, когда feature_flag = true

как

Class A
{
  if(feature_flag == false)
    UtilityClass obj_util;

  A(int x,int y,int z)
  {
  }
}

(или)

2) Я не хочу, чтобы конструктор UtilityClass () был Вызывается при создании объекта в A. Я также не хочу преобразовывать UtilityClass в классе A в UtilityClass *, чтобы избежать вызова конструктора, так как существует огромный код, связанный с этим объектом в классе A, и требует изменения во многих компонентах внутри. Но я почти уверен, что ни один из этих путей кода не будет достигнут, когда feature_flag = true.

Я хочу, чтобы оба сценария ios сосуществовали только с решающим условием одного флага (feature_flag). Возможно ли это даже в c ++?

Я что-то слышал о std :: conditional, но не понял, могу ли я применить его в следующем сценарии.

Например, следующее не сработало

// globally accessible variable. can be changed at runtime.
bool feature_flag = true

Class A
{
  std::conditional <feature_flag, UtilityClass, DummyClass> obj_util;

  A(int x,int y,int z)
  {
  }
}

Кроме того, я попытался вставить std :: conditional в файл .h, потому что все определения классов присутствуют в файлах .h в моем проекте, и это также, похоже, не работает.

Обратите внимание, что я не могу создать фиктивный конструктор в UtilityClass или в этом отношении не могу изменить код для UtilityClass.

Любые советы или предложения приветствуются. Спасибо

Ответы [ 3 ]

2 голосов
/ 16 января 2020

Здесь можно использовать нечто похожее на дизайн на основе политики .

Я бы реализовал класс, который хранит UtilityClass на основе специализации шаблона логического флага:

template<bool FeatureActivated> struct Feature;
template<> struct Feature<true> {
    UtilityClass utility;
};
template<> struct Feature<false> {};

Класс A может активировать эту функцию на основе логического значения, заданного в качестве параметра шаблона:

template<bool FeatureActivated>
struct A : public Feature<FeatureActivated> {};

Вы можете использовать A, например:

auto foo() {

    A<true> t;
    auto& feature = t.utility; //compiles

    A<false> t2;
    auto& feature2 = t2.utility; // does not compile

}

Вот полный пример: https://godbolt.org/z/b3Kmo7

Редактировать: Это не позволяет включать или выключать эту функцию во время выполнения.

0 голосов
/ 16 января 2020

Если вы не хотите изменять obj_util на указатель, возможно, было бы разумно изменить его на функцию:

class A {
public:
    A() { std::cout << "Constructor"; }
    void print() { std::cout << "Print"; }
};

bool feature_flag = true;

class B {
public:
    B() : obj_util(feature_flag) {
        if (feature_flag) {
            obj_ptr = std::make_unique<A>();

            // Syntax has to be changed to a function call
            obj_util().print();
        }
    }

private:
    std::unique_ptr<A> obj_ptr;
    A& obj_util() const { return *obj_ptr; }

};

Другой вариант - создать класс-обертку, который копирует интерфейс:

class AWrapper {
public:
    AWrapper(bool enabled) {
        if (enabled) ptr = std::make_unique<A>();
    }
    void print() { ptr->print(); }

private:
    std::unique_ptr<A> ptr;
};

bool feature_flag = true;

class B {
public:
    B() : obj_util(feature_flag) {
        if (feature_flag) {
            // No need to change the syntax
            obj_util.print();
        }
    }

private:
    AWrapper obj_util;
};
0 голосов
/ 16 января 2020

Что означает сохранение указателя на UtitlityClass вместо самого класса. Предпочитаю unique_ptr. Затем, если ваш флаг имеет значение true, создайте класс, иначе у вас будет nullptr. При использовании класса вы должны выполнять проверки nullptr.

Class A
{
public:
  A(int x,int y,int z)
  {
      if( feature_flag == true ){
          // obj_util.reset( new UtilityClass() ); //c++11
          // since c++14
          obj_util = std::make_unique< UtilityClass >();
      }

      // can be anywhere int class
      if( obj_util != nullptr ){
          obj_util->doStuff();
      } 
  }
private:
  std::unique_ptr<UtilityClass> obj_util = nullptr;


}
...