Home > other >  Concept checking on struct members
Concept checking on struct members

Time:10-24

What is the simple, idiomatic way, to check that a specific struct member validates a given concept ?

I tried the following and it does not work because { T::f } yields type float&:

#include <concepts>
struct foo {
    float f;
};

// ok
static_assert(std::floating_point<decltype(foo::f)>);


template<typename T>
concept has_fp_member = requires (T t) {
  { T::f } -> std::floating_point;
};

// fails
static_assert(has_fp_member<foo>);

Where can I "remove" that useless reference being added on { T::f } ? Without making the code super ugly, adding new concepts, etc... my main requirement is that things stay readable !

e.g.

template<typename T>
concept has_fp_member = std::floating_point<decltype(T::f)>;

is very subpar, because my actual concept would check a large set of attributes, and I do not want a mess of std::foo<decltype(T::a)> && std::bar<decltype(T::b)> && ...

Note that I use float as an example but my question is about a general solution for any type / concept.

CodePudding user response:

You might want to use macro:

#include <concepts>
#include <type_traits>

template <class T>
std::decay_t<T> decay_copy(T&&);

#define CHECK_MEMBER(name, type) \
{ decay_copy(t.name) } -> type

template<typename T>
concept has_member_variables = requires (T t) {
  CHECK_MEMBER(f, std::floating_point);
  CHECK_MEMBER(i, std::integral);
};

Demo.

CodePudding user response:

Here's a partial solution but I would like to find something better (inspired from an answer to this question which has been removed)

auto prvalue(auto&& arg) { return arg; }

template<typename T>
concept has_fp_member = requires (T t) {
  { prvalue(T::f) } -> std::floating_point;
};

static_assert(has_fp_member<foo>);

It only supports cases where the member is copy-constructible though.

  • Related