lundi 5 juin 2017

Using std::array and using "array" as name

In my C++ JSON library, I recently had a regression with GCC7. I stripped down the affected code and hope to understand the error.

The code

Consider this header myclass.hpp:

#pragma once

template <typename X>
struct A
{
    struct value_t
    {
        X array;
    };

    static A array()
    {
        return A();
    }

    friend bool operator<(const A& lhs, const A& rhs) noexcept
    {
        return lhs.val.array < rhs.val.array;
    }

    value_t val = {};  
};

As you see, I used the name "array" as member variable name in struct value_t, as name of a static function. I then included the header in the following file:

#include <array>
using std::array; // note this!
#include "myclass.hpp"

int main()
{}

The problem

The code compiles with GCC6 and Clang5 (using -std=c++11), but GCC7 reports:

In file included from example.cpp:3:0:
myclass.hpp: In function 'bool operator<(const A<X>&, const A<X>&)':
myclass.hpp:19:40: error: wrong number of template arguments (1, should be 2)
         return lhs.val.array < rhs.val.array;
                                        ^~~~~
In file included from example.cpp:1:0:
/usr/local/Cellar/gcc/7.1.0/include/c++/7.1.0/array:94:12: note: provided for 'template<class _Tp, long unsigned int _Nm> struct std::array'
     struct array
            ^~~~~
make: *** [all] Error 1

It seems as if the parser reads the "array" in lhs.val.array as std::array and treats the following < as the start of a template list.

The code can be compiled if I make any of the changes below:

  • Remove the using std::array; or move it behind #include "myclass.hpp".
  • Change return lhs.val.array < rhs.val.array; to return (lhs.val.array) < rhs.val.array;.

In addition, either compiler fails if I remove the static A array() function...

My questions

  • Is the code correct in the first place? Am I allowed to use "array" as a name even if I use using std::array;?
  • If the code is correct, is this a bug in GCC7?

Aucun commentaire:

Enregistrer un commentaire