lundi 22 novembre 2021

Clang fails with "static_assert expression is not an integral constant expression" for a static constexpr method of an object within another class [duplicate]

I have the following code snippet:

#include <cstddef>
#include <vector>

template <typename T, size_t CAPACITY>
class Container {
    std::vector<T> storage;
  public:
    static constexpr auto capacity() {
        return CAPACITY;
    }
    ///Some methods where CAPACITY is used
};

class Dummy {
    Container<int, 5> container;
    void dummy() {
        static_assert(container.capacity(), "Does not compile"); ///<===Fails with Clang
        static_assert(decltype(container)::capacity(), "Compiles");
    }
};

int main()
{
    Container<int, 5> container;
    static_assert(container.capacity(), "Compiles");
    static_assert(decltype(container)::capacity(), "Compiles");
}

It compiles fine with gcc (See test)

On clang the first static assert instead gives (See test):

error: static_assert expression is not an integral constant expression
        static_assert(container.capacity(), "Does not compile");
                      ^~~~~~~~~~~~~~~~~~~~
 note: implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function

Which compiler is right? Why is that line of coding failing? Why does it fail only when the object container is declared within a class method and it succeeds in main()? Is the decltype version the only alternative?


Here is a reduced sample that allows to reproduce the problem (thanks to Frank, see it in action)

#include <cstddef>
#include <vector>

struct Foo {
    static constexpr auto capacity() {
        return 12;
    }
};

class Dummy {
    Foo container;
    void dummy() {
        static_assert(container.capacity(), "Does not compile"); ///<===Fails with Clang
        static_assert(decltype(container)::capacity(), "Compiles");
    }
};

int main()
{
    Foo container;
    static_assert(container.capacity(), "Compiles");
    static_assert(decltype(container)::capacity(), "Compiles");
}

Aucun commentaire:

Enregistrer un commentaire