Если мой класс является литеральным классом, тогда избыточно ли объявлять объект моего класса как constexpr? - PullRequest
14 голосов
/ 07 июля 2019

У меня есть класс constexpr Отладка:

struct Debug {
  constexpr Debug(bool a, bool b, bool c) : a(a), b(b), c(c) {}
  bool a, b, c;
  constexpr bool get() const { return a; }
};

int main() {
  Debug dbg(true, false, false); // is dbg constexpr object?
  constexpr Debug dbg2(0, 0, 0); // is constexpr redundant here?
}

Как видите, dbg является объектом constexpr, потому что он инициализируется конструктором constexpr, поэтому, если я квалифицирую его как constexpr, какой смысл в этом?

  • Я не знаю разницы между dbg и dbg2. Спасибо.

Ответы [ 2 ]

11 голосов
/ 07 июля 2019

Существует существенное отличие: только dbg2 может использоваться, когда требуется постоянное выражение. В качестве примера рассмотрим предстоящую функцию C ++ 20, которая допускает произвольные параметры не типового шаблона:

template <Debug> void f() { }

С приведенным выше определением f<dgb2>() будет компилироваться, а f<dgb>() - нет.

f<dgb>();
<source>:7:29: note:   template argument deduction/substitution failed:

<source>:13:12: error: the value of 'dbg' is not usable in a constant expression
   13 |   foo<dbg>();  // ERROR
      |            ^

<source>:10:9: note: 'dbg' was not declared 'constexpr'
   10 |   Debug dbg(true, false, false); // is dbg constexpr object?

живой пример на godbolt.org


Это также важно в C ++ 11. Вы сможете сказать:

template <bool> void g() { }
g<dgb2.a>();

но не:

g<dgb.a>();

живой пример на godbolt.org

4 голосов
/ 07 июля 2019

Простая демонстрация различия двух переменных:

struct Debug {
  constexpr Debug(bool a, bool b, bool c) : a(a), b(b), c(c) {}
  bool a, b, c;
  constexpr bool get() const { return a; }
};

int main() {
  Debug dbg(true, false, false); // dbg is not a constant
  constexpr Debug dbg2(0, 0, 0); // constexpr makes this a constant expression

  // *** Begin demo ***
  dbg.a = false;
  //dbg2.a = false; //< error: assignment of member 'Debug::a' in read-only object
  // *** End demo ***
}

Значение dbg можно изменить, а значение dbg2 нельзя.

Чтобы получить объект Debug, который является константным выражением, вам нужен как квалификатор constexpr в конструкторе (чтобы позволить объекту Debug помечаться как константное выражение), так и квалификатор constexpr в объявление переменной (чтобы пометить этот объект как константное выражение).

...