简体   繁体   中英

g++: range-based for loop not compile without using namespace std;

The following code

#include <iostream>
#include <string>
using namespace std;

template <typename A> std::string to_string(const A& v) {
  bool first = true;
  std::string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail> void debug_out(const Head& H, const Tail&... T) {
  std::cerr << " " << to_string(H);
  debug_out(T...);
}

#define debug(...) std::cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)

int main() {
  int x = 3;
  debug(x);
  return 0;
}

complies with GCC 9.3.0 and outputs [x]: 3 when run. However, if the 3rd line using namespace std; is commented out, the code does not compile and the errors are

prog.cc: In instantiation of 'std::string to_string(const A&) [with A = int; std::string = std::__cxx11::basic_string<char>]':
prog.cc:21:32:   required from 'void debug_out(const Head&, const Tail& ...) [with Head = int; Tail = {}]'
prog.cc:32:3:   required from here
prog.cc:7:3: error: 'begin' was not declared in this scope; did you mean 'std::begin'?
    7 |   for (const auto &x : v) {
      |   ^~~
      |   std::begin
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
                 from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:105:37: note: 'std::begin' declared here
  105 |   template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
      |                                     ^~~~~
prog.cc:7:3: error: 'end' was not declared in this scope; did you mean 'std::end'?
    7 |   for (const auto &x : v) {
      |   ^~~
      |   std::end
In file included from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/string:54,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/locale_classes.h:40,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/ios_base.h:41,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ios:42,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/ostream:38,
                 from /opt/wandbox/gcc-9.3.0/include/c++/9.3.0/iostream:39,
                 from prog.cc:1:
/opt/wandbox/gcc-9.3.0/include/c++/9.3.0/bits/range_access.h:107:37: note: 'std::end' declared here
  107 |   template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
      |       

I know that a ranged-based for loop is not intended to be used on an integer , and the same code (either with or without using name space std; ) does not compile with clang . However, why the statement using namespace std; makes a difference when complied with GCC?

You can check this on wandbox https://wandbox.org/permlink/kp5u1iMYHST83tCa .

The reason is that there exists a method to_string in namespace std . If you rename your method to my_to_string the error message will be independent from the using statement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM