81

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?

ruakh
  • 175,680
  • 26
  • 273
  • 307
Thor
  • 9,638
  • 15
  • 62
  • 137
  • 2
    Which edition and printing of the book do you have? Have you looked for an errata of the book? – Some programmer dude Jul 09 '18 at 06:57
  • @Someprogrammerdude thanks for the reminder. I should definitely check the errata first. – Thor Jul 09 '18 at 06:58
  • 2
    So what version are you reading? I'm sure Bjarne would like to know about this mistake. – StoryTeller - Unslander Monica Jul 09 '18 at 07:03
  • 1
    3.9.2 Unsafe conversions By unsafe conversion we mean that a value can be implicitly turned into a value of another type that does not equal the original value. e.g: int i = 20000; char c = i; Such conversions are called 'narrowing' conversions. double to int, char or bool int to char or bool char to bool – Marichyasana Jul 09 '18 at 07:06
  • 15
    The `float char` is another useful type, especially in swimming pools. Some come with a holder for a beer. – Yakk - Adam Nevraumont Jul 09 '18 at 16:01
  • 1
    _Is this a typo or a valid C++ syntax?_ [Try it](https://wandbox.org/permlink/pLqW3SiRSNyFad2a) (OK, OK, no it isn't valid). – Paul Sanders Jul 09 '18 at 18:19
  • @PaulSanders But then you encounter [stuff like this](https://wandbox.org/permlink/ah5TJ78ZcgO7JgYy) and are like... what? – Izkata Jul 09 '18 at 20:49
  • @Izkata I don't understand - that's perfectly legal. There's just a compiler warning for an unused variable. – Paul Sanders Jul 09 '18 at 20:51
  • @PaulSanders Think about it from a beginner's perspective: It's still combining two datatypes, yet this one is legal for some reason. (I'm not a C++-er and have no idea why that's legal and, for example, [this one isn't](https://wandbox.org/permlink/c8ilMjt941q3uMWk)) – Izkata Jul 09 '18 at 21:14
  • 1
    @Izkata Oh, OK, I can explain that one for you. `long long` is a distinct datatype in C / C++. It is a 64 bit integer these days in practise, even on 32 bit platforms (the integer types are a bit of a mess generally, and there are now about 32767 of them because the standards guys keep making up new ones for no obvious reason). – Paul Sanders Jul 09 '18 at 22:50

4 Answers4

95

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • What was probably the intended code example in the book? – Pedro A Jul 09 '18 at 21:57
  • 8
    @Hamsterrific `char b1 {1000};` (because that would provoke the error mentioned in the comment). I guess Bjarne's typing fingers were tired that day. – Paul Sanders Jul 09 '18 at 22:53
  • 1
    @PaulSanders Tired? He typed an extra `int` there! :-) – Leo Heinsaar Jul 10 '18 at 07:11
  • 1
    @ LeoHeinsaar Lol. OK, too much coffee then :) Or maybe he has a stutter :) – Paul Sanders Jul 10 '18 at 07:47
  • Yeah: fingers tired. It looks like a cut-n-paste error from the example that preceded it. In that prior example, he gives two lines: int a {1000}; // OK [\n] char b {a} // error: int -> char might narrow [\n] and he seems to have cut-n-pasted that example for the next one and missed deleting the "int" part: int char b1 {1000}; // error: narrowing (assuming 8-bit chars) [\n] char b2 {48}; // OK [\n] – L. Scott Johnson Jul 13 '18 at 18:01
24

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.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
10

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.

Alex
  • 948
  • 1
  • 13
  • 17
6

This is wrong in C/C++ syntax. In addition to unions (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
}
P.W
  • 26,289
  • 6
  • 39
  • 76
val - disappointed in SE
  • 1,475
  • 3
  • 16
  • 40