9

The following code gives different results with the g++ 7 compiler and Apple clang++. Did I run into a bug in clang in the alignment of bool output when std::boolalpha is used, or did I make a mistake?

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

template<typename T>
void print_item(std::string name, T& item) {
    std::ostringstream ss;
    ss << std::left << std::setw(30) << name << "= " 
       << std::right << std::setw(11) << std::setprecision(5) 
       << std::boolalpha << item << " (blabla)" << std::endl;

    std::cout << ss.str();
}

int main() {
    int i = 34;
    std::string s = "Hello!";
    double d = 2.;
    bool b = true;

    print_item("i", i);
    print_item("s", s);
    print_item("d", d);
    print_item("b", b);

    return 0;
}

The difference is:

// output from g++ version 7.2
i                             =          34 (blabla)
s                             =      Hello! (blabla)
d                             =           2 (blabla)
b                             =        true (blabla)
// output from Apple clang++ 8.0.0
i                             =          34 (blabla)
s                             =      Hello! (blabla)
d                             =           2 (blabla)
b                             = true   (blabla)
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Chiel
  • 6,006
  • 2
  • 32
  • 57
  • what was the difference? Thanks you Chiel for updating. I can reproduce with Clang 6 too. – gsamaras Sep 21 '17 at 07:25
  • print out put in question too. write results : – saeed Sep 21 '17 at 07:26
  • @gsamaras. I slightly edited the example to better show what goes wrong. – Chiel Sep 21 '17 at 07:39
  • 8
    This is [LWG 2703](https://timsong-cpp.github.io/lwg-issues/2703). – T.C. Sep 21 '17 at 07:43
  • @LWG 2703. That is indeed the case. Then there is no solution to my problem, unfortunately when using clang. – Chiel Sep 21 '17 at 07:53
  • Technically, you can change the C++ library that you link against, but it's not necessarily an easy solution (and doesn't help much if you produce a binary to be executed on other machines). Assuming your real code actually does something like the posted, you could of course specialize the `bool` version of `print_item`, and perform two stringstream outputs, one to form the boolean string, the next to output with width. But that gets rather messy to do that if you have large amounts of variable output. – Mats Petersson Sep 21 '17 at 08:04
  • @MatsPetersson It's really not _that_ bad. You always have the option of replacing your boolean `var` in the stream with `(var ? "true" : "false")`. (Which I guess is what I'll be doing, because this somehow still isn't fixed in libc++.) Hmmm. Though I suppose if you were relying on localization for the strings, that could be messy. Is `std::boolalpha` output localized, normally? – FeRD Sep 27 '21 at 12:26

1 Answers1

6

At T.C. mentioned, this is LWG 2703:

No provision for fill-padding when boolalpha is set

N4582 subclause 25.4.2.2.2 [facet.num.put.virtuals] paragraph 6 makes no provision for fill-padding in its specification of the behaviour when (str.flags() & ios_base::boolalpha) != 0.

As a result I do not see a solution to this with Clang. However, notice that:

  • libc++ implements this exactly.
  • libstdc++ and MSVC apply padding and alignment.

PS: LWG stands for Library Working Group.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Alright. Unfortunately, `libstdc++` isn't too friendly for my c++11 code. – Chiel Sep 21 '17 at 08:45
  • @Chiel that's another issue. Maybe this helps: [Which version of C++ library on Linux conform to the “ISO C++ 11” standard?](https://stackoverflow.com/questions/10824963/which-version-of-c-library-on-linux-conform-to-the-iso-c-11-standard). Good luck! – gsamaras Sep 21 '17 at 08:58