Как я могу определить концепцию для unordered_map, которая обнаруживает свою функцию стирания - PullRequest
3 голосов
/ 02 марта 2020

Я пишу концепцию C ++ для неупорядоченных ассоциативных контейнеров, а именно std :: unordered_map. У меня возникают трудности с обнаружением функции стирания (также вставки, но на данный момент давайте проигнорируем это).

Вот моя попытка концепции, к сожалению, она терпит неудачу, когда я пытаюсь вызвать шаблонную функцию, требующую ее.

template <class _ContainerType_>
concept InsertErasable = requires(_ContainerType_ a)
{
    { a.erase( _ContainerType_::const_iterator) } -> typename _ContainerType_::iterator;
};

Я использую его так:

template<InsertErasable _ContainerType_>
inline void Test123( const _ContainerType_& container )
{
    return;
}

std::unordered_map<std::string, int> map;
::Test123(map);

ошибка C7602: «Test123»: связанные ограничения не выполнены

Использование последней версии Visual Studio 2019.

Он должен обнаружить первую подпись стирания, показанную здесь: https://en.cppreference.com/w/cpp/container/unordered_map/erase

Есть идеи, что я делаю неправильно?

1 Ответ

2 голосов
/ 02 марта 2020

Честно говоря, я никогда не использовал концепции на практике, но мне удалось выяснить, что здесь не так. Код в предложении require должен быть выражением, а не половиной выражения, половиной определения функции. Другими словами, это должно быть выражение, которое будет скомпилировано, если вы поместите его в обычную функцию (https://en.cppreference.com/w/cpp/language/constraints в разделе require). Чтобы исправить вашу проблему, вы должны настроить код внутри концептуального предложения, чтобы он был допустимым выражением C ++. Это можно сделать одним из двух способов. Либо:

template <class _ContainerType_>
concept InsertErasable = requires(_ContainerType_ a)
{
    {a.erase(a.cbegin())} -> typename _ContainerType_::iterator;
};

или

template <class _ContainerType_>
concept InsertErasable = requires(_ContainerType_ a,_ContainerType_::const_iterator b)
{
    {a.erase(b)} -> typename _ContainerType_::iterator;
};

Пример в проводнике компилятора

...