Расширение типов из сравнения

Я знаю следующий код не работает, и я полностью понимаю Зачем. Что я на самом деле не понимаю, так это почему бы и нет:

int main(int argc, char *argv[]) {
std::cout << (atoi(argv[1]) ? "foo" : 'b') << std::end;
}

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

error: operands to ?: have different types ‘const char*’ and ‘char’

Почему бы и нет: С operator<< иметь связь с обоими типами const char* а также charпочему компилятор не выполняет расширение кода, как в шаблоне — что, я думаю, и выполняется.

Например, если бы я имел:

template <class T>
void a(const T& value) {
std::cout << a << std::endl;
}

Я мог бы позвонить либо a("foo") а также a('b')и — я полагаю — компилятор сделает одно расширение функции с именем типа [T = const char*] и еще один с [T = char],

Это может быть простой вопрос о том, что делает C ++, а что нет, но я не вижу, есть ли какой-нибудь угловой случай, который выглядел бы как ошибка, если бы расширение было выполнено.

0

Решение

Это не имеет ничего общего с cout или же operator <<, Выражение

atoi(argv[1]) ? "foo" : 'b'

сам не скомпилирует. 2-й и 3-й операторы, которым вы кормите ?: должен быть либо того же типа, либо типов, которые неявно преобразуются друг в друга.

3

Другие решения

C ++ — это скомпилированный статически типизированный язык и тип выражения должен быть известен во время компиляции. Выражение atoi(argv[1]) ? "foo" : 'b' может быть const char* или же charв зависимости от стоимости argv[1], который не может быть известен во время компиляции. Только когда программа действительно выполняется, это значение известно. Поэтому, когда компилятор пытается превратить это выражение в машинный код, он не может решить, к какому типу обращаться с выражением.

Чтобы увидеть, что это на самом деле не имеет ничего общего с operator<<Просто имейте выражение:

int main(int argc, const char* argv[])
{
atoi(argv[1]) ? "foo" : 'b';
}

Даже это не скомпилируется, дает следующую ошибку:

error: operands to ?: have different types ‘const char*’ and ‘char’
4

Это то, что вы думаете, вы должны просить:

#include <iostream>
#include <utility>
#include <type_traits>
#include <functional>

template<typename Left, typename Right>
auto tri( bool b, Left&& left, Right&& right )
-> decltype( std::forward<Left>(left)() )
{
if (b)
return std::forward<Left>(left)();
else
return std::forward<Right>(right)();
}

int main(int /*argc*/, char *argv[]) {
tri(
atoi(argv[1]),
[]()->std::ostream&{ return std::cout<<"foo"; },
[]()->std::ostream&{ return std::cout<<'b'; }
) << std::endl;
}

но это не то, что ? делает.

C ++ может быть изменен, чтобы делать то, что вы просите, но каскад типов будет расти безгранично. Каждый раз, когда у вас есть выражение, которое может вернуть тип A или введите Bкод вызова должен быть разветвлен, что может привести к дальнейшему разветвлению.

Сигнатуры функций должны быть расширены, чтобы перечислить все типы, которые он «мог» возвращать.

Теперь, хотя в будущем это может быть полезным для C ++, это не то, что сейчас делает C ++. Каждое выражение в C ++ имеет один определенный тип — в коде шаблона, это происходит, когда вы создаете экземпляр шаблона.

Кроме того, возможность иметь поли-тип возвращаемых значений в C ++ даст вам возможности, аналогичные обработке исключений, где функция может возвращать значение или флаг ошибки. Поскольку вызывающий код должен будет автоматически разветвляться всякий раз, когда вы вызываете функцию возвращаемого значения поли-типа, он должен обрабатывать этот флаг ошибки (либо возвращая его как альтернативный тип, либо обрабатывая его локально).

1
По вопросам рекламы [email protected]