6

If compiled with gcc v10 the code below exibits an error but for gcc v9 the code is ok.

template<auto N>
struct A {
    constexpr auto size() const {
        return N;
    }  
};

template<typename T>
void foo1(const T& a) {
    constexpr auto s = a.size(); // Why error here?
}
template<typename T>
void foo2(T a) {
    constexpr auto s = a.size(); // OK
}
int main() {
    A<10> x1;
    foo1(x1);
    foo2(x1);
    A<x1.size()> x2; // OK
    constexpr auto s = x1.size(); // OK
}

In my understanding the memberfunction size() could be called constexpr in all cases. But there is one case where the behaviour of gcc10 changed compared to gcc9: if the argument is passed by const-ref. I don't understand why this should not be constexpr?

Another example:

template<auto N>
struct A {
    constexpr auto size() const {
        return N;
    }  
};

template<typename T>
constexpr void foo1(const T& a) {
    constexpr auto s = a.size(); // Why error here?
    return s;
}
template<typename T>
constexpr auto foo2(const T& a) {
    return a.size(); // Why OK here
}
int main() {
    A<10> x1;
    constexpr auto s1 = foo1(x1);
    constexpr auto s2 = foo2(x1);
}

I don't understand the difference.

wimalopaan
  • 4,838
  • 1
  • 21
  • 39

1 Answers1

4

This is GCC bug 66477. It mentions that GCC wrongly accepts reference-type parameters in constant expressions.

This bug is fixed for GCC 10.


The reason why a.size() is not allowed in constant expressions is mentioned in this post.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • Well, I don't get it right. I added another example to the question. – wimalopaan Feb 20 '20 at 10:01
  • @wimalopaan A constexpr function doesn't require all the expressions in its body to be constant expressions, while the initializer of a constexpr variable must be a constant expression. – xskxzr Feb 20 '20 at 12:31