Bug 71794 - Std::array as an incomplete type in nested name specifier.
Summary: Std::array as an incomplete type in nested name specifier.
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2016-07-07 10:55 UTC by Pawel Bednarski
Modified: 2016-07-07 12:25 UTC (History)
0 users

See Also:
Known to work:
Known to fail:
Last reconfirmed:

Code that won't compile on GCC. (227 bytes, text/x-csrc)
2016-07-07 10:55 UTC, Pawel Bednarski

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Bednarski 2016-07-07 10:55:04 UTC
Created attachment 38851 [details]
Code that won't compile on GCC.

In code attached: MyContainer type works perfectly fine. std::vector works fine as well.

Error message:
$ g++-6 -Wall -Wextra -Wpedantic --std=c++14  main.cpp 
main.cpp: In instantiation of ‘T foo() [with T = std::array<float, 4ul>]’:
main.cpp:39:31:   required from here
main.cpp:16:21: error: incomplete type ‘B<std::array<float, 4ul> >’ used in nested name specifier
     return B<T>::bar();
Comment 1 Jonathan Wakely 2016-07-07 11:42:52 UTC
This is nothing to do with libstdc++, the problem is that you've using int rather than std::size_t

using size_t = decltype(sizeof(0));

template<typename T, size_t N>
  struct array 
     T data[N];

template<typename T, int N>
struct MyContainer 
   T data[N];

template <typename T>
struct B;

template <typename T>
T foo()
    return B<T>::bar();

template <typename T, int N>
struct B<array<T, N>>
  static array<T, N> bar()
      return array<T, N>();

template <typename T, int N>
struct B<MyContainer<T, N>>
  static MyContainer<T, N> bar()
      return MyContainer<T, N>();

int main()
    foo<array<float, 4>>(); // incomplete type
    foo<MyContainer<float, 4>>();

foo<array<float, 4>> returns B<array<float, (size_t)4>> which doesn't match your partial specialization of B<array<float, (int)4>>

Clang accepts this, but G++ and EDG reject it for the same reason.
Comment 2 Jonathan Wakely 2016-07-07 11:43:44 UTC
If you fix your partial specialization it works with all compilers:

template <typename T, std::size_t N>  /* correct type */
struct B<std::array<T, N>>
  static std::array<T, N> bar()
      return std::array<T, N>();
Comment 3 Jonathan Wakely 2016-07-07 11:51:02 UTC
VC++ accepts it too, so it's two for and two against.


template<unsigned N> struct X { };

template<typename T> struct Y;

template<int N> struct Y<X<N>> { };

template<typename T> Y<T> f() { return {}; }

auto x = f< X<1> >();
Comment 4 Pawel Bednarski 2016-07-07 12:25:23 UTC
That's right Jonathan, thanks!