Home > Net >  concept constraints don't apply
concept constraints don't apply

Time:09-15

I've the following code

#include <cstdint>
#include <concepts>

template <class T>
concept has_id = requires(T) {
    T::Id;
    std::same_as<uint8_t[16], decltype(T::Id)>;
};

The has_id concepts ensure that a type has the member Id with type uint8_t[16].

However, when writing the following example it works even though the Id has type uint8_t[17] which is invalid.

#include <cstdint>
#include <iostream>

class Sample
{
public:
    static constexpr uint8_t Id[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,10,11};
};

template<has_id T>
void print_id()
{
    std::cout.setf(std::ios_base::hex);

    std::cout << "{" << (int)T::Id[0];

    for(auto i=1; i < sizeof(T::Id);   i)
        std::cout << ", " << (int)T::Id[i];

    std::cout << "}";
}

int main()
{
    print_id<Sample>();

    return 0;
}

I've tried it on Visual C 2022 17.3 and Clang 14 and they give the same result, any idea why?

CodePudding user response:

template <class T>
concept has_id = requires(T) {
    T::Id;
    std::same_as<uint8_t[16], decltype(T::Id)>;
};

Confirms that the expression T::Id compiles, and that the expression std::same_as<....> compiles. It doesn't check whether the latter is true or false.

You can just write

template <class T>
concept has_id = requires(T) {
    T::Id;
    requires std::same_as<uint8_t[16], decltype(T::Id)>;
};

to change the constraint from must compile to must be true.


Note GCC 12 helpfully emits the following warning with your original code:

<source>:7:2: warning: testing if a concept-id is a valid expression;
  add 'requires' to check satisfaction [-Wmissing-requires]

CodePudding user response:

Right now, your requirement just checks that std::same_as<uint8_t[16], decltype(T::Id)>; compiles. You want to use nested requirements to require that the value of std::same_as<...> is actually true. A fixed requirement would look like:

#include <cstdint>
#include <concepts>

template <class T>
concept has_id = requires(T) {
    T::Id;
    requires std::same_as<uint8_t[16], decltype(T::Id)>;
};

CodePudding user response:

Here is my version which is more simple then other answers:

template <class T>
concept has_id = std::same_as<const uint8_t[16], decltype(T::Id)>;

Note also extra const you (and others) have missed in expression.

Live demo

  • Related