Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« : 31-08-2010 07:38 » |
|
Вопрос такой: тип параметров некой функции может со временем поменяться, поэтому: как указать компилятору, чтобы он не делал неявных приведений типов аргументов при вызове этой функции, то есть чтобы ругань происходила даже если пытаемся переменную типа short передать в агрумент типа int ?
По всему коду это не требуется, а только для конкретной одной функции, для контроля
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #1 : 31-08-2010 09:02 » |
|
В голову приходит только шаблонная функция, инстанцированная только для типа int, например. Как-то так: template <typename Type> Type foo(Type);
int foo(int val) { return 2 * val; }
int main() { const int c = 1; int x = foo(c); // OK, use int foo(int) const short c2 = 2; int x2 = foo(c2); // error LNK2001: unresolved external symbol "short __cdecl foo<short>(short)" (??$foo@F@@YAFF@Z)
return 0; }
Наверное, можно этот подход улучшить, чтобы сообщение об ошибке было более чётким, а не на этапе линковки. У конструкторов ещё есть explicit.
|
|
« Последнее редактирование: 31-08-2010 09:06 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 31-08-2010 09:46 » |
|
так, а если значения по ссылке передавать - прокатит ? Даже без шаблона ведь должно?
explicit - это как
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #3 : 31-08-2010 11:31 » |
|
По ссылке не прокатит, т.к. будет создана временная переменная. С шаблоном прокатывает только потому, что при поиске наилучшего соответствия шаблон будет лучше подходить, его-то компилятор и подставит, не заботясь о том, инстанцирован ли он. explicit - это указание компилятору, что конструктор может использоваться только явно: class boo { int m_; public: boo(int m) : m_(m) { std::cout << "boo(int)" << std::endl; } };
class ddd { int m_; public: explicit ddd(int m) : m_(m) { std::cout << "ddd(int)" << std::endl; } };
int main() { boo x1 = boo(1); // OK, "boo(int)" boo x2 = 1; // OK, "boo(int)" ddd y1 = ddd(1); // OK, "ddd(int)" ddd y2 = 1; // error C2440: 'initializing' : cannot convert from 'int' to 'ddd' return 0; }
explicit хорошо помогает, если мы не хотим, чтобы к нашему классу происходило неявное преобразование, например, при передаче того же int в функцию, где аргументом выступает ddd.
|
|
« Последнее редактирование: 31-08-2010 11:32 от Вад »
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #4 : 31-08-2010 12:03 » |
|
я бы сказал, что в данном случае надо просто обернуть параметы функции классом (можно даже с паблик членами) у которого сделать explicit конструктор или даже для читаемости сделал бы просто проверку, ну примерно так class checkParam { public: explicit checkParam(int _m, char _p) {} };
void f(int m, char p) { checkParam(m, p);
// do what you need }
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Антон (LogRus)
|
|
« Ответ #5 : 31-08-2010 12:59 » |
|
мне кажется в новом стандарте были какие-то поползновения на это счёт
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 31-08-2010 13:34 » |
|
По ссылке не прокатит, т.к. будет создана временная переменная.
нет нет, я не так выразился, я имею в виду - передавать ссылку void F(type& t1) { }
я точно не могу сказать, но вроде всегда в таких случаях компилятор резво реагирует, даже если различие только в модификаторе const
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #7 : 31-08-2010 13:59 » |
|
Ну что я могу сказать... попробуй Но я всё именно так и понял
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #8 : 01-09-2010 04:30 » |
|
нет нет, я не так выразился, я имею в виду - передавать ссылку void F(type& t1) { }
я точно не могу сказать, но вроде всегда в таких случаях компилятор резво реагирует, даже если различие только в модификаторе const что-то я не понял в чём фишка Я в своё время делал реализацию енумов которые нельзя было явно приводить к другим типам (задрало меня, что народ енумы в инты превращает, а по коду разбросаны магические числа), ну так вот я слела шаблонный класс обёртку который вел себя, как енум до тех пор пока его не пытались приводить в инт или другой енум (бывали случаи). Далее я в функции/методы передавал/возвращал только этот тип, какое-то время убил, что бы найти все места, где было некорретное использование (компиляцию яное дело разорвало, ну я к этому и стремился) вот как-то так
|
|
« Последнее редактирование: 01-09-2010 04:51 от Антон (LogRus) »
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 01-09-2010 04:46 » |
|
да, с const я не то сказал. А вот с типами вроде нормально: void Fi(int& t) { }
void Fc(char& t) { }
int i=0; char c=0; Fi(i); Fi(c);//error Fc(i);//error Fc(c);
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #10 : 01-09-2010 04:52 » |
|
я предыдущий пост дополнил
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 01-09-2010 05:02 » |
|
так я ж не про енумы, я про типы аргументов функций
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #12 : 01-09-2010 05:14 » |
|
ну это как концепция
|
|
|
Записан
|
Странно всё это....
|
|
|
Вад
|
|
« Ответ #13 : 01-09-2010 08:29 » |
|
да, с const я не то сказал. А вот с типами вроде нормально
Но тогда нарушается другое: ты уже не можешь передавать в функцию константные данные. Если у тебя аргумент не изменяется, а является лишь исходными данными, это тоже не слишком хорошо. Можно, конечно, пойти дальше, и требовать передавать константный указатель на int...
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 01-09-2010 08:37 » |
|
ты уже не можешь передавать в функцию константные данные
да, но, предположим, обеспечим, что везде будут передаваться объекты, а не константы А оптимизация потом сделает своё белое дело (наверное). Зато, цель достигнута
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #15 : 01-09-2010 09:09 » |
|
ты уже не можешь передавать в функцию константные данные
да, но, предположим, обеспечим, что везде будут передаваться объекты, а не константы А оптимизация потом сделает своё белое дело (наверное). Зато, цель достигнута А константные объекты - это уже не объекты? По-моему, если что-то в функции не меняется, то оно по возможности и должно описываться как const (особенно ссылочные типы) - дабы более чётко декларировать свои намерения. Равно как описание методов класса как константных, если они не намереваются менять внутреннее состояние объекта. Чтобы неповадно было.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #16 : 01-09-2010 16:29 » |
|
я бы всё таки поместил всё в прокси объекты и передавал бы прокси объекты это будет железно работать
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 01-09-2010 16:40 » |
|
прокси объекты - это шо за зверь такой ? )
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #18 : 01-09-2010 21:18 » |
|
это, например, то, что я написал в самом начале)))))))))))))))
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 02-09-2010 03:58 » |
|
lapulya, вернее - в самом середИне
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #20 : 02-09-2010 04:31 » |
|
lapulya, это совсем не то вот то: template <typename T> class DataHolder; typedef DataHolder<int> DHint; typedef DataHolder<int> DHshort; ....... DHint a; DHshort b; int aa; short bb; a = aa; //ok aa = a; //ok a = bb; //err bb = a; //err
void foo(DHint a, DHshort b);
т.е. в функцию можно передать только те типы, которые позволит твой проси объект, при этом run-time оверхед будет практически нулевой, т.к. почти всё, если не всё, будет посчитано в compile-time
|
|
« Последнее редактирование: 03-09-2010 07:51 от Sel »
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 02-09-2010 04:47 » |
|
не пойму - а почему без тела класса , так можно что ли ? template <typename T> class DataHolder;
то есть, по сути, тогда DataHolder<int> - эквивалентен int , плюс невозможно неявное приведение
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #22 : 02-09-2010 08:28 » |
|
не пойму - а почему без тела класса , так можно что ли ? template <typename T> class DataHolder;
то есть, по сути, тогда DataHolder<int> - эквивалентен int , плюс невозможно неявное приведение
чтобы ты сам реализовал
|
|
« Последнее редактирование: 03-09-2010 07:51 от Sel »
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #23 : 02-09-2010 08:59 » |
|
ясно ) Я просто подумал, что тут что-то неизвестное произошло, вот и спросил ))
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #24 : 02-09-2010 11:08 » |
|
Антон (LogRus), можно как ты предложил, а можно и как я. Оборачиваем проверку в ifdef и в release версию это не входит, тогда вообще ничего лишнего выполняться не будет
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Антон (LogRus)
|
|
« Ответ #25 : 03-09-2010 03:19 » |
|
lapulya, твоё решение не требует ifdef, в любом случае компилятор выкинет эту строчку. что касается debug/release, то это вообще не аргумент кто сказал что дебаг версию хоть кто-то будет собирать я их собираю только в случае, если найдена ошибка и много моих знакомых тоже. на старой работе дебаг версия вообще не собирался в принцепе - какие-то ошибки из буста лезли, исправлять было некогда
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #26 : 03-09-2010 05:03 » |
|
а я наоборот всегда в дебаге делаю, студия много ошибок подсказывает (на обкатку пользователям делаю релиз, конечно )) )
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #27 : 03-09-2010 06:45 » |
|
ну это ты один, а когда у тебя разработчиков 200 не необходимый комплект тестовых бинарников в релизе собирается час а в дебаге и того больше при этом весит пару гигов вместе с отладочной инфой, то тут встаёт вопрос: "А оно мне надо?" в общем в итоге моё мнение : если защита от дурака не несёт рантайм-оверхеда в релизе, то незачем её отключать
|
|
|
Записан
|
Странно всё это....
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #28 : 03-09-2010 07:18 » |
|
если есть экономия времени - то да, я бы тоже в релизе только сидел, но ведь одинаково по времени. Хотя, я не замерял точно
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #29 : 05-09-2010 20:19 » |
|
))) это ребилд олл занимает столько много времени, а билд намнооооого меньше, дай бог пару минут. Если дольше, то скорее всего слишком много ненужных инклудов в хеадерах.
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Вад
|
|
« Ответ #30 : 05-09-2010 20:26 » |
|
))) это ребилд олл занимает столько много времени, а билд намнооооого меньше, дай бог пару минут. Если дольше, то скорее всего слишком много ненужных инклудов в хеадерах.
или много шаблонов. Что в случае Антона волне возможно
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #31 : 06-09-2010 16:53 » |
|
ну все равно чтобы сборка шла так долго, туча хеадеров (которые инклюдятся) должно измениться, очень слабо мне в это верится. Причем большая часть этих изменившихся хеадеров должны быть на низком уровне архитектуры (т.е. на них должно опираться много других, в противном случае он них мало что завист), а это еще больше сомнительно...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Антон (LogRus)
|
|
« Ответ #32 : 06-09-2010 18:55 » |
|
Много-много-много шаблонов, pdb файл одной из библиотек (парсер файлов, весь из себя шаблонный для ускорения парсинга) 800 мег, собирается 20 минут ну это так специфика реализации я почти всегда стараюсь делать ребилд всего перед коммитом, студия не всегда видела зависимости между файлами и грабли бывали в не предсказуемых местах, слишком сильно связанный код местами.
|
|
|
Записан
|
Странно всё это....
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #33 : 07-09-2010 23:01 » |
|
Во наплодили то... я почти всегда стараюсь делать ребилд всего перед коммитом... слишком сильно связанный код местами. вот я об этом и говорил. Хотя подтвержу, ребилд иногда (редко правда) помогал, поскольку после некоторых обычных сборок была жопа. А чего вы подобные ребилды не делаете на отдельной машине, так оно никому не мешает... и время не жрет... ну это я так мысли в слух... можно даже повесить скрипт на VCS по простановке метки с новой мажорной (ну или как надо) составляющей запускался ребилд, с выкладкой результатов на шару (или тоже в VCS), а потом можно и тесты запустить... )))
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Антон (LogRus)
|
|
« Ответ #34 : 08-09-2010 06:37 » |
|
Клиенту отгружается сборка собранная системой автосборки, которая за одно гоняет тесты: юнит, функциональные, интеграционные но имхо не круто, когда ты отгружаешь изменения ломая модули коллег и узнаёшь об этом завтра, когда придёт письмо от автосборки Поэтому я делаю полный ребилд, не от того что боюсь собрать кривые бинарники, а для того, чтобы максимально приблизить точку выявления проблем компиляции в смежных подсистемах. Вообще мы одно время пользовались (уже на старой работе к слову сказать) утилитой IncrediBuild она очень сильно ускоряла процесс сборки, но потом кончился триал, а денег на нормальную версию не выделили (точнее я ушел когда процесс был в стадии согласования) Рекомендую утилиту, можно поставить её на мощные серваки для разгрузки машин разработки Суть: выявить зависимости исходников, разослать на разные машины исходный код для сборки, потом на локальной машине всё скомпоновать Это дело интегрируется в IDE есть схожее решение для Linux/unix и бесплатное
|
|
|
Записан
|
Странно всё это....
|
|
|
|