Подтвердить что ты не робот

Тернарный оператор + конструктор С++ 11 из initializer_list

При разработке приложения у меня была следующая проблема. Я хотел вернуть пустой std::list<string>, когда указанный указатель функции был нулевым, или результат этой функции в противном случае. Это упрощенная версия моего кода:

typedef std::list<std::string> (*ParamGenerator)();

std::list<std::string> foo() {
    /* ... */
    ParamGenerator generator = ...;
    if(generator)
        return generator();
    else
        return {};
}

Тем не менее, я обычно предпочитаю использовать тернарный (?:) оператор в этих случаях, поэтому я попытался использовать его таким образом (как обычно):

return generator ? generator() : {};

Но получилась эта ошибка:

somefile.cpp:143:46: error: expected primary-expression before ‘{’ token
somefile.cpp:143:46: error: expected ‘;’ before ‘{’ token

Означает ли это, что я не могу использовать тернарный оператор для возврата объектов, созданных с помощью их конструктора, из initializer_list? Есть ли какая-то особая причина для этого?

4b9b3361

Ответ 1

Стандартная запись в 8.5.4.1: Инициализация списка

Примечание. Можно использовать инициализацию списка

  • как инициализатор в определении переменной (8.5)
  • как инициализатор в новом выражении (5.3.4)
  • в операторе return (6.6.3)
  • как аргумент функции (5.2.2)
  • как индекс (5.2.1)
  • в качестве аргумента для вызова конструктора (8.5, 5.2.3)
  • как инициализатор для нестатического элемента данных (9.2)
  • в mem-initializer (12.6.2)
  • в правой части присваивания (5.17)

Ничто из них не является тройным оператором. Более минималистичный return 1?{}:{}; тоже недопустим, что вы хотите невозможно.

Конечно, вы можете явно вызвать конструктор std::list<std::string>{}, но я бы рекомендовал выписать if - else -block, как вы уже это делали.

Ответ 2

Когда вы выполняете {}, компилятор не знает того типа, который вы ожидаете, поэтому это просто бессмысленное выражение, которое компилятор не знает, что делать. Обе стороны : оцениваются отдельно, и только тогда компилятор будет жаловаться, если типы не совпадают. Я бы просто сделал это:

return generator ? generator() : std::list<std::string>();

Ответ 3

Если вам действительно нравится тернарный оператор, вы можете попробовать что-то вроде этого:

return generator ? generator() : decltype(generator()) { "default value", "generator was empry" };

он будет работать, даже если вы измените типы возвращаемых позже.