Объявление переменной с двумя типами: "int char"

Я новичок C++, и я читаю Bjarne Stroustrup Программирование: принципы и практика с использованием C++.

В разделе, посвященном 3.9.2 Небезопасные преобразования, автор упомянул

Когда инициализатор является целым литералом, компилятор может проверить фактическое значение и принять значения, которые не подразумевают сужение:

int char b1 {1000};     // error: narrowing (assuming 8-bit chars)

Я озадачен этой декларацией. Он использует два типа (int и char). Я никогда не видел такого объявления в Java и Swift раньше (два языка, с которыми я довольно хорошо знаком). Является ли это опечаткой или действительным синтаксисом C++?

Ответ 1

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

Он не упоминается ни в одной из ошибок на странице Bjarne Stroustrup (4-я печать и ранее), хотя это странно. Это достаточно явная ошибка. Я предполагаю, что, поскольку он прокомментировал //error некоторые люди замечают ошибку в самой декларации.

Ответ 2

Книга неверна.

Последовательность токенов int char b1{1000}; не является семантически допустимым C++.

Вы пытаетесь объявить b1 более чем одним типом, что не имеет смысла.

Ответ 3

Это неверно. В C/C++ многотипные декларации могут быть достигнуты с помощью профсоюзов. Например:

union {
    int i;
    char c;
} var;

var.i = 42;
/* OR */
var.c = ‘c;

Хранилище такое же, поэтому.c и.i - это только дескрипторы одного типа для одного и того же значения.

Ответ 4

Это неверно в синтаксисе C/C++. В зависимости от union (см. Ответ @Alex) существует C++ способ хранения только одного из доступных типов, называемых std::variant (тип-безопасный союз):

#include <variant>
#include <string>

int main()
{
    std::variant<int, float> v, w;
    v = 12; // v contains int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
      std::get<float>(w); // w contains int, not float: will throw
    }
    catch (std::bad_variant_access&) {}

    std::variant<std::string> v("abc"); // converting constructors work when unambiguous
    v = "def"; // converting assignment also works when unambiguous
}