4

I'm having the following issue with constexpr arrays and CRTP. While the first line works the second yields an error that Der::arr does not exist. Given that the first line should execute in a constexpr context, I'm not sure what the issue is with the second.

template <typename Der>
struct Base
{   
    static constexpr std::size_t val = Der::arr.size(); // This works
    static constexpr std::array<int, Der::arr.size()> r = {}; // yields error
};

struct Derived : Base<Derived>
{
    static constexpr std::array<int, 10> arr = {};
};

int main(int argc, char **argv){
    Derived d;  
    return d.val;
}

Error:

<source>:12:43: error: no member named 'arr' in 'Derived'
    static constexpr std::array<int, Der::arr.size()> r = {}; // yields error
                                     ~~~~~^
<source>:15:18: note: in instantiation of template class 'Base<Derived>' requested here
struct Derived : Base<Derived>
                 ^
1 error generated.
Compiler returned: 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
user3882729
  • 1,339
  • 8
  • 11
  • This appear like a compiler bug, acting as a feature. Replacing `Der::arr.size()` in the second line with `val` also gives error. The error then moves to the line-1 of incomplete type. Ideally both lines should have given error. – iammilind Jan 06 '21 at 04:11
  • I think both those lines are UB, but I'm not sure. You might want to tag this with [language-lawyer] as well. – cigien Jan 06 '21 at 04:59
  • 1
    Does this answer your question? [CRTP -- accessing incomplete type members](https://stackoverflow.com/questions/35428422/crtp-accessing-incomplete-type-members) – Rane Jan 06 '21 at 08:02
  • 1
    @cigien No, the first one is valid. The fundamental difference is (late) initialization vs. declaration/instantiation here. For the second one (required direct instantiation), the compiler would need the full actual class layout information that he is actually defining in the same time. Rane's link should clarify that in detail. – Secundi Jan 06 '21 at 08:09
  • 1
    It seems that only gcc is able to pick this up ([godbolt](https://godbolt.org/z/qYnvcf)). P.S. I recommend using _godbolt_ when dealing with difficult error messages. – Rane Jan 06 '21 at 08:15

0 Answers0