Declaring a variable with two types: "int char"
C++Type ConversionInitializationUniform InitializationNarrowingC++ Problem Overview
I'm a C++ beginner, and I'm reading Bjarne Stroustrup's Programming: Principles and Practice Using C++.
In the section on 3.9.2 Unsafe conversions, the author mentioned
> When the initializer is an integer literal, the compiler can check the actual value and accept values that do not imply narrowing: > > int char b1 {1000}; // error: narrowing (assuming 8-bit chars)
I'm puzzled by this declaration. It uses two types (int
and char
). I have never seen such declaration in Java and Swift before (the two languages I'm relatively familiar with). Is this a typo or a valid C++ syntax?
C++ Solutions
Solution 1 - C++
It's a mistake in the book. That is not a valid C++ declaration, even without the supposed narrowing conversion.
It isn't mentioned in any of the erratas on Bjarne Stroustrup's page(4th printing and earlier), though, which is odd. It's a clear enough mistake. I imagine since it's commented with //error
few people notice the mistake in the declaration itself.
Solution 2 - C++
The book is wrong.
The token sequence int char b1{1000};
is not semantically valid C++.
You are trying to declare b1
with more than one type, which makes no sense.
Solution 3 - C++
It is wrong. In C/C++ the multi-type declarations can be achieved via the use of unions. Eg:
union {
int i;
char c;
} var;
var.i = 42;
/* OR */
var.c = ‘c’;
The storage is the same, so .c and .i are just per-type handles to the same value.
Solution 4 - C++
This is wrong in C/C++ syntax. In addition to union
s (see @Alex answer), there is a C++ way to store only one of available types called std::variant
(type-safe union):
#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
}