I'm writing a concept that checks if a type can be used in an expression that composes 2 functions:
template<typename T>
concept C = requires(T t) {
f(g(t));
};
i.e., I want to check if for a given object t
of type T
, I can call g(t)
and then use the resulting value as an argument to f
. e.g.,
auto g(int) -> float;
auto g(char) -> double;
void f(float);
void f(double) = delete;
static_assert(C<int>); // g(int) returns a float, so f(float) is called.
static_assert(not C<char>); // g(char) returns a double, but f(double) is deleted
This works just fine.
However, I want to split up the calls to f
and g
because 1) g
may take additional arguments (that don't depend on T
) resulting in a verbose call, and 2) I might want to use the return type/value of g
multiple times inside the concept, so I don't want to repeat the call multiple times.
Naive attempts like the following
auto res = g(t);
f(res);
and
using ret_t = decltype(g(t));
f(ret_t{});
don't work inside concepts.
Is there some way to achieve the splitting up of f(g(t))
in a way that doesn't require writing g(t)
inside the call to f
?
A nested requirement can be an option:
template<typename T>
concept C = requires(T t) {
g(t); // Not strictly needed, I think, but explicit verification might be more readable if the concept fails in a template
requires requires(decltype(g(t)) s) { // Can reuse s how many time we want
f(s);
};
};
And yes, requires requires is required here to make sure f(s)
is verified as well.