Search code examples
c++c++20c++-concepts

What does this statement mean in C++ concept and why it cannot works


I'm trying C++20 features, and I want to use concept to restrain the template to pass only the class with a member named List and its type should be std::vector<int> . Here is the foreword.

To do this without using concept, I will write this code:

class RandomClass
{
public:
    std::vector<int> List;
};

typename std::enable_if<std::is_same<decltype(T::List), std::vector<int>>::value>::type
func(T& arg)
{
      ...
}

int main()
{
    auto randomObj= RandomClass();
    func(randomObj);
}

I asked New Bing to use concept to rewrite it, and it gave this:

template<class T>
concept HasList = requires(T t) {
    { t.List } -> std::same_as<std::vector<int>>;
};

template<class T> requires HasList<T>
void func(T& arg)

But this code cannot be compiled, and the compiler gave 'func': no matching overloaded function found .

I then search std::same_as usage and tried this:

template<class T>
concept HasList = requires(T t) {
    std::same_as<AddressListType, decltype(T::List)>;
};

This code worked.

Now here is the questions:

  1. What does the symbol in these statement { t.List } -> std::same_as<std::vector<int>>; mean? I have no idea where this {} and -> come from
  2. Why { t.List } -> std::same_as<std::vector<int>>; cannot work?

Solution

  • There's just one small issue with your concept: The member variable is considered a reference to a vector. Using the following version of the concept should work:

    template<class T>
    concept HasList = requires(T t) {
        { t.List } -> std::same_as<std::vector<int>&>;
    };
    

    Note that this concept is also fulfilled for cases where the member variable type is a reference to non-const, or where List is a static member. You may need to revise the check, if you're bothered about those cases.

    template<class T>
    concept HasList = requires
    {
        { &T::List } -> std::same_as<std::vector<int> T::*>; // check, if the T::List is a pointer to a non-static member variable of type std::vector<int> 
    };
    

    In:

    { t.List } -> std::same_as<std::vector<int>>;
    

    t.List is an expression, and std::same_as<std::vector<int>> is a concept that must be satisfied. Specifically:

    std::same_as<X, std::vector<int>>
    

    must be satisfied for X being the type of the expression t.List.