0

The following code has different compile results. From the error message I'm receiving it seems there's a confusion about operators precedence () and <<. I can easily overcome this issue by using a function. However I would like to understand and to know:

a) Which compiler it's evaluating correctly the expression? MSVC2017 seems more logical to me.

b) Is there an workaround still using MACROs?

Full sample code I used.

#include <cstdlib>
#include <typeinfo>
#include <sstream>
#include <iostream>

#ifndef NDEBUG
#define  EXPR_INSPECT(param_)\
         ( (std::ostringstream{} << "< " #param_ " [" << typeid(param_).name() << "] > : " << param_).str() )
#else
#define  EXPR_INSPECT(param_)\
         (param_)

#endif //NDEBUG
int main(int argc, char *argv[])
{
   auto        ull_x    {99LLU};
   std::string string_x {"Checking..."};

   std::cout << EXPR_INSPECT(   ull_x) << std::endl;
   std::cout << EXPR_INSPECT(string_x) << std::endl;

   return EXIT_SUCCESS;
}

MSVC2017 works perfectly!

G++ 8.2.0 (MSYS2/MINGW) issues the following error: 'std::basic_ostream::__ostream_type' {aka 'class std::basic_ostream'} has no member named 'str' Attempts to call str() on ostream instead of ostringstream.

EDIT:

The problem here can also be reproduced by clang using Wandbox. Here is a minimal example:

#include <sstream>
#include <iostream>

int main()
{
   auto s = std::ostringstream{};
   decltype(((std::ostringstream{}) << "< "))::nothing;
   decltype((s << "< "))::nothing;
}

In wandbox, clang found the second type std::basic_ostream, while the first type std::basic_ostringstream. That's very strange.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
Jacinto Resende
  • 343
  • 2
  • 13
  • 1
    May I suggest you using less macros? –  Oct 07 '18 at 11:50
  • 1
    What do you mean by `there's a confusion about operators precedence`? `operator<<`s usually return `std::ostream&`. – tkausl Oct 07 '18 at 11:50
  • @Nicky C. Suggestion accepted, but for purpose of the question it's irrelevant. With or without macros the behavior is the same. One compiler accepts it and works the other refuses it. – Jacinto Resende Oct 07 '18 at 11:56
  • Cannot reproduce the "MSVC2017 works perfectly" part. MSVC produces the same error as GCC. https://godbolt.org/z/YjUfjz –  Oct 07 '18 at 11:56
  • I suspect that `NDEBUG` is defined in your VC++ target. – molbdnilo Oct 07 '18 at 11:58
  • @molbdnilo Make sense. https://godbolt.org/z/wlWkDa –  Oct 07 '18 at 12:01
  • 1
    Simplified [mcve]: https://godbolt.org/z/tpum91 – Richard Critten Oct 07 '18 at 12:07
  • 2
    @NickyC Compiler Explorer might be buggy. I can actual reproduce OP's problem on my machine with clang. Wandbox also gives [this](https://wandbox.org/permlink/ay0sysKewbVwVDOU) *extremely bizarre* output. (Note in the return type becomes `std::basic_ostringstream` in one of the case) – llllllllll Oct 07 '18 at 12:26
  • @Nicky C. Well I'm actually using MSVC 2017(v141) and it works. Without any kind of optimization and /W3 level. – Jacinto Resende Oct 07 '18 at 12:31
  • For what it's worth, I could not reproduce the problem using g++ 8.2.0 on my machine (with `-std=c++11`). Could MSYS2/MINGW be pulling in some pre-C++11 headers? – Eljay Oct 07 '18 at 12:33
  • clang's problem is due to this template function: https://github.com/llvm-mirror/libcxx/blob/master/include/ostream#L1034, which includes all rvalues. I don't know whether it's standard conformant. Maybe your MSVC version also has similar highly-inclusive template function catching all rvalue. – llllllllll Oct 07 '18 at 13:32
  • In my very modest opinion there's no problem with CLANG or MSVC. g++ is not evaluating correctly the expression. If I put an expression between braces (no matter the operator I use) I expect it to be evaluated primarily and result used subsequently. – Jacinto Resende Oct 07 '18 at 14:57

0 Answers0