I want to write a C++ concept which checks if a given type is supported by the numeric_limits library or not. I wrote the following code to do this:
// test.cc
#include <limits>
template<typename T>
concept UsableType = requires(T v)
{
{std::numeric_limits<T>::min()} -> T;
{std::numeric_limits<T>::max()} -> T;
};
template<UsableType T>
class MyClass
{
private:
T val;
public:
void set(T v)
{
val = v;
}
};
int main()
{
MyClass<int> obj;
obj.set(1);
return 0;
}
However, when I try to compile this using g++ -std=c++23 test.cc I get
test.cc:6:44: error: return-type-requirement is not a type-constraint
6 | {std::numeric_limits<T>::min()} -> T;
| ^
test.cc:7:44: error: return-type-requirement is not a type-constraint
7 | {std::numeric_limits<T>::max()} -> T;
| ^
Why do I get this error when numeric_limits supports int?
>Solution :
The error is due to the fact that on the right of -> you need a concept, not a type. This should compile:
#include <limits>
#include <concepts>
template<typename T>
concept UsableType = requires(T v)
{
{std::numeric_limits<T>::min()} -> std::same_as<T>;
{std::numeric_limits<T>::max()} -> std::same_as<T>;
};
However, std::numeric_limits<T> (and it’s member functions min() and max()) will exist whether or not there is any meaningful specialisation and they will always return T() (see example online). Use std::numeric_limits<T>::is_specialised to verify if it actually has any meaning.
template <typename T>
concept UsableType = std::numeric_limits<T>::is_specialized;
See it online (no error for int, error for std::string)