How to test if member is integral in concept?

Viewed 212

I'm trying to define a concept that tests if a particular member variable (in the example, 'x'), exists and is an integral type. I'm getting stumped though, since v.x returns an int& and thus the std::integral check fails. How can I make this work?

#include <concepts>

template <typename T>
concept isIntegralX = requires(T v) {
    {v.x} -> std::integral;
};

template <typename T>
requires isIntegralX<T>
void bar(const T& base)
{
}

class Foo
{
public:
    int x{0};

    void baz()
    {
        bar<Foo>(*this);
    }
};

int main()
{
    return 0;
}

Error:

note: the expression 'is_integral_v<_Tp> [with _Tp = int&]' evaluated to 'false'
3 Answers

You can change the concept as:

template <typename T>
concept isIntegralX = std::is_integral_v<decltype(T::x)>;

decltype(T::x) yields the exact type int here.

For multiple members you can

template <typename T>
concept isIntegralXandY = std::is_integral_v<decltype(T::x)> && std::is_integral_v<decltype(T::y)>;

I'm getting stumped though, since v.x returns an int& and thus the std::integral check fails. How can I make this work?

You can try doing an explicit cast to turn the lvalue expression into an rvalue:

template <typename T>
concept isIntegralX = requires(T v) {
    { decltype(v.x)(v.x) } -> std::integral;
    // Or you could write: `{ static_cast<decltype(v.x)>(v.x) } -> std::integral;`
    // ...
};
// ...

To reply to OP's further asked question posted as a comment under songyuanyao's answer. See here for details about std::conjunction. In general, you would want to check <type_traits> for type-related metaprogramming utilities provided by C++.

template <typename T>
concept is_x_and_y_integral = std::conjunction_v<
  std::is_integral<decltype(T::x)>,
  std::is_integral<decltype(T::y)>
>;
Related