I have a class like this:
struct FooImpl {
public:
using Bar = int;
};
I would like to declare that FooImpl::Bar
is an int
through a concept.
This does the job:
template<typename Foo>
concept FooConcept = requires(Foo foo) {
{ std::vector<typename Foo::Bar>() } -> std::same_as<std::vector<int>>;
};
static_assert(FooConcept<FooImpl>);
Is there a more elegant way of doing this? I tried:
{ (typename Foo::Bar)() } -> std::same_as<int>;
But the compiler does not seem happy with this.
CodePudding user response:
First, the reason { (typename Foo::Bar)() } -> std::same_as<int>;
doesn't work is because of most vexing parse typename-specifier can’t be a declarator, and cannot be used within a C-styly-cast parentheses.* To make it work, you should use a brace init instead:
template<typename Foo>
concept FooConcept = requires(Foo foo) {
{ typename Foo::Bar{} } -> std::same_as<int>;
};
* Corrected by @DavisHerring from the comment
Second, if the only constraint you have is to make sure a certain nested type is the same as another, you can simply use std::same_as
:
template<typename Foo>
concept FooConcept = std::same_as<typename Foo::Bar, int>;
Last, some terminologies:
I would like to declare that
FooImpl::Bar
is anint
through a concept.
Declaring FooImpl::Bar
is an int
was already done by the using statement(using Bar = int
). What you probably meant is:
- You want to declare a concept for a type
T
that requiresT::Bar
to be anint
.
Or:
- You want to constraint a type
T
thatT::Bar
is anint
through a concept.