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::Baris anintthrough 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
Tthat requiresT::Barto be anint.
Or:
- You want to constraint a type
TthatT::Baris anintthrough a concept.
