简体   繁体   中英

Integral template parameter. error: use of 'this' in a constant expression

I tried to find a similar answered question in SO but without success. Question is why it is considered as error to use at compile time known at compile time value of template parameter of known at compile time type? Common sense tells me, that this code can be OK. What is wrong in this case? Thanks!

#include <array>

using Cont = std::array<int, 2>;

class A
{
    Cont a_ = {};

public:
    int& at(bool first)
    {
        static_assert(sizeof(a_) / sizeof(int) == 2); // OK
        static_assert(a_.size() > 1); // error: non-constant condition for static assertion. error: use of 'this' in a constant expression
        return a_[first ? 0 : 1];
    }
};

at compiler explorer

UPDATE : it looks like dublicate but may be not because in the question under link the speech is about run-time evaluation, but here looks like a_.size() can be evaluated in compile-time.

UPDATE2 More clear example (after considering answers and comments)

#include <array>

using Cont = std::array<int, 2>;

// OK
void checkSize(const Cont& b)
{
    static_assert(b.size() == 2);
}

class A
{
    Cont a_ = {};

public:
    constexpr void checkSize() const
    {
        Cont b = {};
        static_assert(b.size() == 2); // OK
        static_assert(sizeof(a_) / sizeof(int) == 2); // OK
        static_assert(a_.size() == 2); // error: non-constant condition for static assertion. error: use of 'this' in a constant expression
    }
};

shows that the problem in this is involved to evaluate a_.size() . But why it is needed there, while a_ is known by compiler as non-virtual type and size() can be evaluated in compile time, may be is another question, so I'll check first answer.

std::array::size , even though a constexpr function, isn't a static function. This means it requires an object instance to be invoked.

In this particular case, at isn't constexpr , therefore this isn't either and in turn _a . Since _a isn't constexpr , the result of _a.size() isn't constexpr too.

† Even if it is, the body still isn't considered constexpr .

a_ is a member of the class A .

a_.size() is a simplification of this->a_.size() because size is not a static function, which means that in order to access a_ , you have to access this .

this is a pointer to a class A and is NOT a compile time constant making your static_assert fail.

Using template is probably easier :

template<int N>
class B {
    std::array<int, N> a_;
    public:
    int& at(bool first)
    {
        static_assert((sizeof(a_) / sizeof(int)) == 2, "Sizeof operator"); // OK
        static_assert(N > 1, "Size method"); // No problem here
        return a_[first ? 0 : 1];
    }

};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM