Применение общих имен методов

Примечание. Это дополнительный вопрос к this.

У меня есть группа классов шаблонов, которые делают совершенно разные вещи совершенно по-разному, используя совершенно разные типы данных. Однако они имеют общие имена методов. Например, Get(), Set(), Resize() и т. д. являются допустимыми методами для каждого из рассматриваемых классов. Кроме того, они принимают аргументы в том же порядке. Это позволяет обобщенным недружественным функциям работать с каждым из классов. Упрощенный пример:

template <typename Class, typename Datatype>
void Insert(const Class<Datatype>& Object, const std::size_t Index, const Datatype Value)
{
    Object.Resize(Object.Size() + 1);
    for (std::size_t CurrentIndex = Object.Size() - 1; CurrentIndex > Index; CurrentIndex--)
    {
        Object.Set(CurrentIndex, Object.Get(CurrentIndex - 1));
    }
    Object.Set(Index, Value);
}

Прямо сейчас я просто полагаюсь на свою собственную память, чтобы правильно определить все соответствующие методы. Есть ли способ заставить компилятор применять определение правильных методов? Если нет, есть ли лучший способ сделать это?


person Maxpm    schedule 15.04.2011    source источник


Ответы (4)


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

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

Затем, если аргумент шаблона является производным от этого базового класса, неспособность реализовать требуемую функцию вызовет ошибку компоновки (из-за попытки вызвать функции базового класса, которые не определены). Скорее всего, это будет легче диагностировать, чем типичную ошибку компиляции, связанную с шаблоном.

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

person Mike Seymour    schedule 15.04.2011
comment
+1 за первую часть, но я думаю, что проверка того, получен ли аргумент шаблона из определенной базы, усложняет использование кода. По крайней мере, я бы не ожидал, что код шаблона будет вести себя таким образом. - person pmr; 15.04.2011
comment
@pmr: Да, я тоже не уверен, что это хорошая идея. Комментарий о том, что если вы хотите получить более качественную диагностику, используйте производный от этого класса, вероятно, лучше, чем принудительное выполнение чего-то, что не является строго необходимым. - person Mike Seymour; 15.04.2011

То, что вы ищете, называется "concepts" и используется для быть функцией C++0x, но исключена из нового стандарта.

Есть несколько реализаций для C++03, но их сложнее использовать и, возможно, они не стоят затраченных усилий. например Проверка концепции Boost

gcc также имеет параметр --enable-concept-check, хотя я не совсем уверен, как он работает с пользовательским кодом.

person pmr    schedule 15.04.2011

Компилятор уже применяет определение этих методов, отказывая вам в создании экземпляра шаблона для типов, которые не предоставляют необходимых методов.

К сожалению, сообщения об ошибках компиляторов для шаблонов, не поддерживающих создание экземпляров, часто трудно расшифровать.

Вы можете задокументировать требования к типу в комментариях. Посмотрите, как стандарт C++ определяет требования к типам, такие как Assignable, CopyConstructible, EqualityComparable, LessThanComparable, а также требования к типам в стандартных контейнерах.

person Kristopher Johnson    schedule 15.04.2011
comment
Конечно, это приводит к ошибке «метод не найден», но есть ли более чистый способ? - person Maxpm; 15.04.2011
comment
@Maxpm Что для вас более чистый способ? - person BЈовић; 15.04.2011
comment
@Vjo Ну, я не знаю. Вот почему я спросил. :П - person Maxpm; 15.04.2011
comment
Я не думаю, что есть более чистый способ заставить компилятор применять/проверять требования к типу. Вы можете задокументировать требования в комментариях. Взгляните на то, как стандарт C++ определяет требования к типам, таким как Assignable, CopyConstructible, EqualityComparable, LessThanComparable и т. д. - person Kristopher Johnson; 15.04.2011

Вы можете использовать интерфейс.

См. этот вопрос: Как вы объявляете интерфейс в C++?

person Daniel A. White    schedule 15.04.2011
comment
Интерфейс (или абстрактный базовый класс) не обязательно то, что ему нужно. Ему нужен определенный набор имен функций, но типы возвращаемых значений и другие аспекты этих функций могут не обязательно быть одинаковыми. - person Kristopher Johnson; 15.04.2011
comment
Я не могу использовать чисто виртуальные методы, потому что производные классы будут использовать произвольные возвращаемые типы, а шаблонные виртуальные методы, очевидно, заставят гнусавых демонов преследовать меня. - person Maxpm; 15.04.2011