Тернарный оператор + конструктор С++ 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
? Есть ли какая-то особая причина для этого?
Ответы
Ответ 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" };
он будет работать, даже если вы измените типы возвращаемых позже.