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.