C ++ правила автоматического свертывания - PullRequest
0 голосов
/ 23 сентября 2019

Стандарт сообщает, как будет выполняться этот код?

Примечание: во время компиляции невозможно определить, какое значение условия оценивается ниже.

Будет ли сгенерированный код иметьдва пути?Один, где v свернут до r-значения, когда условие истинно, и другой, где v будет l-значением, когда условие ложно.

Или это будет наихудший случай, и v сворачивается в l-значение для обоихслучаи?

Или это просто определяется реализацией?

struct SomeClass { std::vector<std::string> vec_member_; };

void f(const SomeClass& d, bool condition) {
  auto&& v = (condition) ? 
                std::vector<std::string>{ "fallback case" }
              : d.vec_member_;
  for(auto&& e : v) {
    ... // operate on e (Read only)
  }
}

Извините за форматирование.Я использую Android для редактирования и не могу исправить раздел кода после редактирования.

Ответы [ 3 ]

4 голосов
/ 23 сентября 2019

Выражения в C ++ имеют типы.Это включает в себя ?: выражения.

Ваше ?: выражение имеет тип std::vector<std::string>const.const происходит из-за того, что вы обращаетесь к d.member, а rvaluenness происходит из-за того, что одна ветвь ? имеет значение prvalue.

Полный код компиляции, который демонстрирует это:

struct SomeClass {
  std::vector<std::string> vec_member_;
};
void f(bool condition, const SomeClass& d) {
  static_assert(
    std::is_same_v<
      decltype((condition) ? std::vector<std::string>{ "fallback case" } : d.vec_member_),
      std::vector<std::string>const
    >
  );
  auto&& v = (condition) ? std::vector<std::string>{ "fallback case" } : d.vec_member_;
  for(auto&& e : v) {
    (void)e;
  }
}

auto&&v становится std::vector<std::string> const&&.Для переменной-члена он привязывается к копии.Для значения r оно переходит во временную материализованную привязку к ссылке rvalue v.

Живой пример .

2 голосов
/ 23 сентября 2019

Каждое выражение C ++ относится только к одной категории значений.

(condition) ? 
  std::vector<std::string>{ "fallback case" } : 
  d.vec_member_

не является исключением.

Условное выражение - это lvalue, если второй и третий операнды оба являются lvalue.В противном случае это prvalue.

В этом случае второй операнд не является lvalue, поэтому все условное выражение является prvalue.Он будет привязан к rvalue-ссылке, поэтому auto&& сворачивается в него.

2 голосов
/ 23 сентября 2019

Предполагается, std::vector<std::string> SomeClass::vec_member_; Тип:

(condition) ? std::vector<std::string>{ "fallback case" } : d.vec_member_;

Будет const std::vector<std::string>, поэтому вы создаете копию в ложном случае и работаете с временным в обоих случаях.

...