Home > front end >  Concept for using statement inside class
Concept for using statement inside class

Time:11-27

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 an int 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 requires T::Bar to be an int.

Or:

  • You want to constraint a type T that T::Bar is an int through a concept.
  • Related