[c++] template operator []

doublemother

Есть у меня некий класс вида:
class A {
private:
vector<void *>args;
public:
void add(void *arg) {
args.push_back(arg);
}
template <typename T> T &operator [](int i) {
return *reinterpret_cast<T*>(args[i]);
}
};

Я его наполняю неким набором значений:
        A a;
a.add(new string("Hahaha";
a.add(new int(23;
a.add(new double(24.3;

Не могу понять, как теперь правильно подставлять шаблон.
Работает запись вида
a.operator []<string>(0)
, но наверняка должен существовать нормальный синтаксис. Знает ли кто-нибудь, как именно надо?)

klyv

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

barbos

А че бы не использовать что-то типа

template<typename T> void at(int i, T *dst) const
{
*dst = *reinterpret_cast<T*>(args[i]);
}

?

klyv

не так гламурно - ссылочкой возвращать круче, мона ++ делать итп.

barbos

Ссылку сначала не заметил, можно на T const **dst заменить )
Вообще, некоторые coding-style гайды настоятельно рекомендуют
удерживаться себя от перегрузки операторов :) Тем более в такой
форме.

agent007new

но наверняка должен существовать нормальный синтаксис. Знает ли кто-нибудь, как именно надо?)
Другого варианта нет. Тип возвращаемого значения не может быть выведен из выражения, поэтому его всегда нужно указывать как параметр шаблона

agent007new

Вообще, некоторые coding-style гайды настоятельно рекомендуют
удерживаться себя от перегрузки операторов
Что за глупость? По крайней мере, нормальные coding-style гайды (в том числе, С++ Coding Standarts) нормально к этому относятся. Обычно не рекомендуют перегрузку только в том случае, если она меняет привычный смысл оператора

doublemother

Жаль, я всё-таки надеялся, что можно.
Спасибо :)

barbos

Насколько я помню, в coding-style от google заявляется то,
что я указал. Интернетов под рукой нет - проверить не могу.
Основные претензии к перегруженным операторам в том, что
а) за простым синтаксисом может скрываться сложная чего-то
вычисляющая функция.
б) иногда перегружают таким образом, что изменяется
привычный смысл оператора
В coding-style гайде проще запретить то, что не приносит
явной пользы, чем в каждом конкретном случае проверять
субъективную оценку нативности смысла оператора или его
вычислительную легкость.
А в данном конкретном примере такой оператор вообще не
дает никакого выигрыша, усложняя код разными
"a.operator[]<gloomy_type>(i)".

agent007new

Насколько я помню, в coding-style от google заявляется то,
что я указал. Интернетов под рукой нет - проверить не могу.
Вот что я нашел в Google-CodeStyle:
Do not overload operators except in rare, special circumstances.
Эти редкие специальные случаи очень часты для библиотечного generic кода. Во-первых, можно одинаково обрабатывать встроенные типы (указатели, массивы) и пользовательские типы (что можно, конечно, сделать и без этого, но довольно криво). Во-вторых, правильная интуитивнопонятная перегрузка операторов очень сильно облегчает жизнь. Плюс еще какие-нибудь перегрузки оператора new. А также офигенно полезная перегрузка оператора .
Основные претензии к перегруженным операторам в том, что
а) за простым синтаксисом может скрываться сложная чего-то
вычисляющая функция.
И что? Если написать фукнцию станет что-то понятнее? Если у меня, например, есть прокси-контейнер, который содержит индексируемые объекты в базе и на вызов оператора [] ходит в базу за этими самыми объектами, это плохо? Вполне интуитивный смысл оператора и ничего страшного, в том что там какие-то сложные вычисления происходят.
б) иногда перегружают таким образом, что изменяется
привычный смысл оператора
Это, согласен, не хорошо, хотя тоже не всегда - пример boost::spirit (о нем чуть ниже)
В coding-style гайде проще запретить то, что не приносит
явной пользы, чем в каждом конкретном случае проверять
субъективную оценку нативности смысла оператора или его
вычислительную легкость.
Если кто-то не знает, когда нужно перегружать оператор, а когда нет, показывая свое "умение" перегружать операторы, лепит это куда ни попадя, то это всего лишь говорит о качестве программиста. Я считаю глупо запрещать какие-то вещи из-за того, что их кто-то не может использовать, тем более, что очень много можно получить от этого пользы. Конечно, если, скажем, вся команда такая, то может это и лучший вариант (ну или разогнать нах такую команду). Для примера, в stl почти все перегружает какой-нибудь оператор (в общем-то, stl и задает интуитивную понятность для многих операторов). В бусте многие библиотеки перегружают операторы. Очень хороший пример, когда грамотная перегрузка операторов очень сильно облегчает понимание boost::spirit - ЕБНФ практически идеально ложится на синтаксис С++
А в данном конкретном примере такой оператор вообще не
дает никакого выигрыша, усложняя код разными
"a.operator[]<gloomy_type>(i)".
Здесь я и не говорю, что это подходящее место

klyv

И что? Если написать фукнцию станет что-то понятнее? Если у меня, например, есть прокси-контейнер, который содержит индексируемые объекты в базе и на вызов оператора [] ходит в базу за этими самыми объектами, это плохо? Вполне интуитивный смысл оператора и ничего страшного, в том что там какие-то сложные вычисления происходят.
Это называется "реализация интерфейса", в этом ничего страшного.
Эти редкие специальные случаи очень часты для библиотечного generic кода. Во-первых, можно одинаково обрабатывать встроенные типы (указатели, массивы) и пользовательские типы (что можно, конечно, сделать и без этого, но довольно криво). Во-вторых, правильная интуитивнопонятная перегрузка операторов очень сильно облегчает жизнь. Плюс еще какие-нибудь перегрузки оператора new. А также офигенно полезная перегрузка оператора .
Перегрузка оператора new - исключение, т.к. её порой не обойти, а вот в чём полезность перегрузки ?

agent007new

Это называется "реализация интерфейса", в этом ничего страшного.
Про это в том пункте и шла речь, что ничего страшного в этом нет
Перегрузка оператора new - исключение, т.к. её порой не обойти, а вот в чём полезность перегрузки ?
В возможности однотипно обрабатывать встренные функции и объекты, хотя, с появлением bind и более продвинутых вещей, практически отпала необходимость "ручной" перегрузки, но здесь я больше имел ввиду именно саму ее возможность

barbos

1. Моя фраза о том, что "настоятельно не рекомендуют" - это преувеличение.
2. В остальном согласен с тобой, за некоторым исключением.
Исключение: Каким бы ни было качество программист, требуется, чтобы
он сохранял внимательность в некоторых случаях. И если гайд построен
таким образом, чтобы программист обращал внимание на проблемные
элементы, то это хороший гайд.

agent007new

Исключение: Каким бы ни было качество программист, требуется, чтобы
он сохранял внимательность в некоторых случаях. И если гайд построен
таким образом, чтобы программист обращал внимание на проблемные
элементы, то это хороший гайд.
Вообще, это зависит от подробности и объема гайда: если гайд расписывает каждый шаг. В нем, например, упоминается, что нужно давать переменным осмысленные имена, то стоит и это написать. Вопрос перегрузки операторов я бы поставил на уровень с осмысленными именами переменных. Мне не приходит в голову ситуаций, когда перегрузка может что-то сильно испортить. Запутать, аналогично плохим именам, - да, но испортить - вряд ли

naska79

По мне, так данная проблема из-за того, что вводится темплейтный метод нетемплейтного класса. Если сделать темплейтный класс, у него будет нормально используемый operator [].

doublemother

Это само собой. Только темплейтный класс мне нафиг не нужен. Придётся делать через at :)
Оставить комментарий
Имя или ник:
Комментарий: