Odd resolving solution for C ++ and g ++ namespace vs clang ++

It started with an observation. I changed the code that looks a bit like this (edit: I pulled out the designated initializers here that were also not in the source code):

struct S {
    enum E { E1, E2 } member;
}

// file1.cc
S v1 = { S::E1 };

// file2.cc
S v2 = { S::S::E2 };

Note that file2.ccover-qualifies E2. However, this works in both g ++ and clang ++. (Change 2: g ++ on this particular virtual machine - g ++ - 5.4.1, but the source code went through earlier and later versions of g ++, as well as several versions of clang.) Indeed, we can write:

S v3 = { S::S::S::S::S::S::S::E1 };

( S:: ), . , S struct, , . , , .

-POD-:

struct S {
    S() { std::cout << "made an S" << std::endl; }
    enum E { E1, E2 } member;
}

( #include) . Clang g++ . clang:

namespace.cc:8:3: error: no matching constructor for initialization of 'S'
S x = { .member = S::S::E1 };
namespace.cc:3:8: note: candidate constructor (the implicit copy constructor)
      not viable: cannot convert argument of incomplete type 'void' to
      'const S &' for 1st argument
struct S {
       ^
namespace.cc:3:8: note: candidate constructor (the implicit move constructor)
      not viable: cannot convert argument of incomplete type 'void' to  &&'
      for 1st argument
struct S {
       ^
namespace.cc:4:3: note: candidate constructor not viable: requires 0 arguments,
      but 1 was provided
  S() { std::cout << "made an S\n"; }
  ^
1 error generated.

g++:

namespace.cc:8:28: error: could not convert ‘{E1}’ from ‘<brace-enclosed initializer list>’ to ‘S’
 S x = { .member = S::S::E1 };

, . ?

, . :

#include <iostream>

struct S {
  S() { std::cout << "made an S\n"; }
  enum E { E1, E2 } member;
};

int main() {
  std::cout << S::S::S::S::S::E1 << std::endl;
#ifdef DECL
  S::S::S var;
#endif
  return 0;
}

( -DDECL) :

$ clang++-3.9 -std=c++11 -Wall -O namespace.cc
$ ./a.out
0
$ g++ -Wall -std=c++11 -O namespace.cc
$ ./a.out
0

(No S , , clang member .) main, , g++, clang

$ clang++-3.9 -std=c++11 -DDECL -Wall -O namespace.cc
$ ./a.out 
0
made an S
$ g++ -std=c++11 -DDECL -Wall -O namespace.cc
namespace.cc: In function ‘int main()’:
namespace.cc:11:3: error: ‘S::S’ names the constructor, not the type
   S::S::S var;
   ^
namespace.cc:11:11: error: expected ‘;’ before ‘var’
   S::S::S var;
           ^
namespace.cc:11:14: error: statement cannot resolve address of overloaded function
   S::S::S var;
              ^

, ? "" ?

+4
2

. . S::S::S var ( ) ? , class.qual#2:

, 34 - C:

  • , -, C, C (Clause [class])

  • - -, -, , inested-name-specifier simple-template-id inested-name-specifier,

C.

, struct S::S::S var. clang 3.9 .

, . S::S - .

+3

- C, ++ . ++. , COD (C-like). .

, , ++. ++ ( , , ).

gcc , . struct.

+3

Source: https://habr.com/ru/post/1691814/


All Articles