У меня дилемма. Предположим, у меня есть шаблон класса:
template <typename ValueT>
class Array
{
public:
typedef ValueT ValueType;
ValueType& GetValue()
{
...
}
};
Теперь я хочу определить функцию, которая получает ссылку на класс и вызывает функцию GetValue (). Я обычно рассматриваю следующие два способа:
Метод 1:
template <typename ValueType>
void DoGetValue(Array<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}
Метод 2:
template <typename ArrayType>
void DoGetValue(ArrayType& arr)
{
typename ArrayType::ValueType value = arr.GetValue();
...
}
Почти нет разницы между этими двумя методами. Даже вызов обеих функций будет выглядеть одинаково:
int main()
{
Array<int> arr;
DoGetValue(arr);
}
Теперь, какой из двух является лучшим? Я могу вспомнить некоторые минусы и плюсы:
Преимущества 1 метода:
Параметр является реальным классом, а не шаблоном, поэтому пользователю проще понять интерфейс - очень очевидно, что параметр должен быть массивом. В методе 2 вы можете догадаться только по названию. Мы используем ValueType в функции, поэтому он более понятен, чем когда он скрыт внутри Array и должен быть доступен с помощью оператора scope.
Кроме того, ключевое слово typename может сбивать с толку многих опытных программистов, не разбирающихся в шаблонах.
Способ 2 плюсы:
Эта функция более "верна" своей цели. Когда я думаю, если это так, мне не нужен класс Array. Что мне действительно нужно, так это класс, который имеет метод GetValue и тип ValueType. Это все. То есть этот метод является более общим.
Этот метод также меньше зависит от изменений в классе Array. Что если параметры шаблона Array изменены? Почему это должно влиять на DoGetValue? На самом деле все равно, как определяется массив.
Каждый раз, когда у меня такая ситуация, я не уверен, что выбрать. Какой у тебя выбор?