Home > database >  "The associated constraints are not satisfied" with custom requires clause
"The associated constraints are not satisfied" with custom requires clause

Time:10-07

In one of my projects, I'm getting the error "the associated constraints are not satisfied" for one of my C 20 concepts. It appears to me that my code is correct, so I must misunderstand something about the language.

I have rewritten the code to remove all of the obviously extraneous details.

Here are the include statements:

#include <array>
#include <memory>

The constraint I'm defining is on the member function Afunc below:

template<typename BLikeType>
class A {
public:
    A(std::shared_ptr<C> c_) : c_(std::move(c_)) {}

    template<typename... Args>
    requires requires (BLikeType t, Args... args) {
        {t.Bfunc(c_->Cfunc(args...))};
    }
    std::array<double, sizeof...(Args)> Afunc(Args... args) {
        return c_->Cfunc(args...);
    }

private:
    std::shared_ptr<C> c_;
};

The classes B and C were written in a way to try to satisfy the constraint above. I use an std::array<double, 2> only so that readers understand that the variadic template in A is necessary.

class C {
public:
    C() {}

    std::array<double, 2> Cfunc(double a, double b) {
        return { a, b };
    }
};

I have also written a class B for the template parameter BLikeType in A. It is given below:

class B {
public:
    B(){}

    double Bfunc(std::array<double, 2> my_array) {
        return my_array[0]   my_array[1];
    }
};

I then try to test this constraint in my main function:

int main() {
    C c{};
    std::shared_ptr<C> c_ptr = std::make_shared<C>(c);

    A<B> a(c_ptr);
    std::array<double, 2> answer = a.Afunc<double, double>(.1, .2); // Error: the associated constraints are not satisfied

    return 0;
}

Why does this give the error that my constraint is not satisfied?

CodePudding user response:

template<typename... Args>
requires requires (BLikeType t, Args... args) {
    {t.Bfunc(c_->Cfunc(args...))};
}
std::array<double, sizeof...(Args)> Afunc(Args... args) {
    return c_->Cfunc(args...);
}

The requires-clause is not a complete-class context, so it can't see later-declared class members like c_. You can move the declaration of c_ earlier in the class, but even then it won't see it with any necessary cv-qualification if the function is const (since the function declarator isn't seen at that point). Using a trailing requires-clause can solve that issue. In this case there's no extra cv-qualification to add, though, so it doesn't really matter.

  • Related