+50.7
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
namespace inter {
template<typename X>
struct tplClass {
private:
X _priv;
public:
tplClass(const X _generator) {
this->_priv = _generator;
return;
}
tplClass(const tplClass<int>& _a) {
this->_priv = _a.get();
return;
}
const X get(void) const {
return this->_priv;
}
};
template<typename X>
const tplClass<X> operator+(const tplClass<X>& _lha, const tplClass<X>& _rha) {
return tplClass<X>(_lha.get()+_rha.get());
}
}
int main(int argc, char* args[], char* envs[]) {
tplClass<int> a(5);
tplClass<double> b(3.1);
tplClass<double> c = a + b;
return 0;
}
1. Всё упрощено до невозможности. Описано только то, что необходимо для узрения говнокода.
2. Несмотря на то, что решение существует в очень известной книжке, я напоролся на говнокод лично, пока программу писал. Искал несколько дней проблему... Ну да... Бывает...
3. Говнокод заключается в том, что данный код не компилируется.
P.S. Если видите, что где-то есть дыра, то говорите, возможно я опечатался (злобная администрация исправить не даст), возможно в данном коде плюг опущен, возможно дыра у меня в голове. Конструктивная критика приветствуется.
P.P.S. Если вы решили просто написать, что (C++ == "говно") is true , то, пожалуйста, прошу вас как людей порядочных и воспитанных, имеющих совесть и ум, пройдите мимо. Если у вас нит ни ума, ни совести, ни порядочности, то можете писать про "естественную говнистость" C++, милости прошу.
Запостил:
interested,
30 Октября 2009
Понятно, что на самом деле всё происходит в моём пространстве имён...
Такие вещи же по ссылке возвращаются. [/quote]
Правильнее сказать, что я не сторонник подобных мер.
Benin пишет правильно, что многое зависит от ситуации. Например, если мне пришлось возвращать "тяжёлый тип".
Мне такое делать приходилось. Но после недолгого "перепроектирования" получилось добавить сущность, которая что-то в себя инкапсулировала и агрегировалась другими классами.
Если по делу, то это учебный недоговнокод.
Никогда раньше не сталкивался с такой особенностью неявного привидения типов.
ну да operator+ тут не сможет инстанциироваться из-за неоднозначности (мб int, мб double)
Компилятор вообще говорит, что не найден оператор сложения.
Если написать два честных, нешаблонных, сложения, то код скомпилируется и верно выполнится
const tplClass<X> operator+(const tplClass<X>& _lha, const tplClass<Y>& _rha) {
return tplClass<X>(_lha.get()+_rha.get());
}
естественно, зависит от первого параметра.
можешь специализировать шаблон, но вообще, это ахтунг - делать такие операторы.
Матрицы не складываются...
Если по-вашему писать (я пробовал), то выходит фиговрина =[
С тремя параметрами та, же фиговина... Но там я чувствовал, что есть двусмысленность...
И пошёл искать траблу...
Вот нашёл через некоторое время. Я сначала думал посмотрю в библиотеке стандартной, там же есть complex<typename _Tp>, да так и не разобрался, очень что-то замудрёно всё...
думаю, лучше не парить мозг а написать шаблонный Add.
что-то вроде
template<typename R, typename X, typename Y>
const tplClass<R> Add(const tplClass<X> x, const tplClass<Y> y)
{
return tplClass<R>(x.get() + y.get());
}
Мне вот очень хотелось именно такую вычурню сделать =] Вот прям жёсткое желание себе в попу вставить, да поглубже =] И ведь нашёл у Скотта Мейерса как раз такую штуку! =]
Глядим.
Можно сварганить две функции: int int и double double ; По сути ни одна из них не может удовлетворить поставленной перед компилятором задачи. Он и не находит функцию. Вот в чём дело!
Однако, если функции будут не шаблонные, а ручками прописанные, то код сработает.
То есть, при выводе шаблона не работает кастинг типов!!!
Ан нифига...
c = a.Add<double>( b ); чтобы можно было явно указать тип параметра.
Всегда Ваш, К.О.
Но в конструкторе здесь есть некорректность.
Если вам известны проблемы, то вы прямо и напишите: так вот и так, возникают неприятности. Я перестану писать его там...
Например я пытаюсь на очердной сетке, создать новый объект обсчёта, от этой сетки. Однако, метод обсчёта требует выполнения некоторых критериев устойчивости. Я проверяю эти критерии для переданной сетки значений начиная с самого простого. Если какой-то из критериев не выполняется, я логирую проблему и выхожу из конструктора. Создающая обсчёт программа или клиентский объект, увидев, что произошла ошибка удалит счётный объект и попытается прибегнуть к другой схеме или вовсе прекратит работу, сообщив, что всё уже вне пределов действия модели.
Простой пример, метод прогонки, который хочет, чтобы для переданной матрицы граничные прогоночные коэффициенты были бы меньше одного, а сумма побочных диагоналей меньше основной. Проверить начальные коэффициенты очень легко, дело трёх операций, а вот подсчёт суммы -- операция трудоёмкая. Если коэффициенты уже неверны, продолжать проверку и обсчёт нет смысла, нужно обращать матрицу приближённо, итерациями.
Тебе даже не придеться делать удаление обьекта, тк компилятор сделает это за тебя.
Если за тебя что-то делает компилятор, то ты уверен в этом, тк он точно ничего не забудет, в отличии от тебя. А на практике часто где-нибудь да забывают...
Генерация исключения в конструкторе может приводить к непредвиденному результату.
И такие вот у меня конструкторы встречаются someClass(unsigned int size):_array(valarray<double>(0.0,size)) { }
А вообще он просто не нужен в тех функциях, в которых ты не возращаешь параметры. Незнаю зачем писать несколько лишних букв.
Говнокод с return сейчас продемонстрирую.
Естественно несколько return'ов - это для пущей надёжности. Хоть один, да сработает. Поэтому он не краснея смотрит начальнику в лицо и говорит, что пишет самый надёжный код на планете.
1) есть неприятность с конструктором:
tplClass(const tplClass<int>& _a)
зачем привязка только к int?
2) в принципе, можно было бы сделать, чтобы int+double и double+int возвращали double, если бы был typeof. Скажем, так:
может быть в boost::mpl есть что-нибудь заместо typeof. Некоторые компиляторы предоставляют что-то подобное. Но, опять же, хотелось бы обходиться без обязательного наличия конструкторов по-умолчанию.
Можно попробовать, например, через boost::mpl описать правила привидения типов, в соответствии со стандартом. Например,
, но, наверное, это чересчур геморно :)
не надо делать имена с подчёркиванием в начале, ни одним, ни двумя, - они зарезервированы для компиляторов и писателей стандартных библиотек.
Мне приведение типов было нужно всё равно, для обращения и для других функций, думалось, что всё с шаблонным сложением сработает, а оно не захотело. Я запостил. =]
>зачем привязка только к int?
Этот неявный конструктор и есть неявное преобразование из tplClass<int> в любой другой. Предполагается, что их тут два tplClass<int> и tplClass<double>.
Предлагаете другой способ неявного привидения типов?
Вообще было бы правильным решением сделать код, который бы генерировал код для неявного преобразования шаблонных классов для используемых в программе конкретизаций, типы которых неявно приводимы. (и что было бы тогда с tplClass< tplClass<int> >? Как вычислить все типы к которым он приводится...)
>не надо делать имена с подчёркиванием в начале
Буду иметь в виду.
Я не пишу обычно подчёркиваний. яПишутВотТакВотССамогоДетства. Просто я код "передрал" и для однообразия всем добавил _ =] По-моему из STL для какого-то сложения был код, я его выдрал и перекроил, чтобы сюда поднять.
Я же сначала в STL и полез поискать решение проблемы, а не в книжки... Думаю, разберусь в коде, сделаю, как они. А там нету... =[