Можно ли делать C++ RAII с неиспользуемым/временным объектом?
#include <iostream>
#include <sstream>
class Log
{
public:
template <typename T>
Log& operator , (const T &t)
{
s << t;
return *this;
}
~Log
{
std::cout << s.str << std::endl;
}
private:
std::stringstream s;
};
int main(int, char *[])
{
int value = 7;
Log "test: ", value;
return 0;
}
P.S. в конструкторе такого лога можно добавлять в начало результирующей строки дату, время, номер треда, etc.
я, например, делал такую хрень для логированияА зачем использовать стрёмную запятую вместо вполне уместного здесь оператора "<<"?
ну на мой вкус запятая выглядит естественнее и набирается проще, чем дурацкие "клювики"
может ты вот это ищешь?
XmlSection(xml, "asd"); убивается сразу.брюки превращаются.... в элегантные шорты : http://ideone.com/5I6a3t
А может как-нибудь по-другому можно лучше сделать?посмотри на всякие xml билдеры
первое, что нагуглилось: http://code.google.com/p/java-xmlbuilder/
легко ложится на C++
struct SimpleXMLWriterЕще раз, в какие шорты?
{
private:
class SimpleXMLSection;
struct SimpleXMLWriter {
SimpleXMLWriter;
SimpleXMLSection &begin_section(const string & tag);
SimpleXMLWriter &end_section;
SimpleXMLWriter &write_value(const string & tag, const string & value);
protected:
SimpleXMLWriter(SimpleXMLWriter const &);
};
struct SimpleXMLSection: public SimpleXMLWriter {
SimpleXMLSection(SimpleXMLWriter &w, string const &tag): SimpleXMLWriter(w) {
tags.push(tag);
}
~SimpleXMLSection {
end_section;
}
};
SimpleXMLSection SimpleXMLWriter::begin_section(const string &tag) {
return SimpleXMLSection(*this, tag);
}
int main {
SimpleXMLWriter xml.
section(xml, "lulz").
write_value("asd", "dsa").
section(xml, "lulz2").
write_value("asdd", "ddsa");
}
Если хочется без копирования, или если родитель не имеет все-таки ярко выраженной стековой семантики, тогда придется немного подлиннее, конечно.
class SimpleXMLSection;
struct SimpleXMLWriter {
SimpleXMLWriter;
SimpleXMLSection &begin_section(const string & tag);
virtual SimpleXMLWriter &end_section;
SimpleXMLWriter &write_value(const string & tag, const string & value);
protected:
SimpleXMLWriter(SimpleXMLWriter const &);
};
class SimpleXMLSection: public SimpleXMLWriter {
SimpleXMLWriter &parent;
SimpleXMLWriter &root;
bool alive;
public:
SimpleXMLSection(SimpleXMLWriter &w, string const &tag): SimpleXMLWriter(w parent(w root(w alive(true) {
root.tags.push(tag);
}
SimpleXMLSection(SimpleXMLSection &w, string const &tag): SimpleXMLWriter(w parent(w root(w.root alive(true) {
root.tags.push(tag);
}
SimpleXMLWriter &end_section {
if(alive) {
alive = false;
root.end_section;
}
else {
parent.end_section;
}
}
~SimpleXMLSection {
if(alive) root.end_section;
}
};
SimpleXMLSection SimpleXMLWriter::begin_section(const string &tag) {
return SimpleXMLSection(*this, tag);
}
int main {
// 's patch hasn't made it into the main tree yet, so this still won't compile.
SimpleXMLWriter xml.
section(xml, "lulz").
write_value("asd", "dsa").
section(xml, "lulz2").
write_value("asdd", "ddsa").
end_section.
write_value("hello", "pinkie-pie");
}
А эта, думаю, еще больше не соберется.
class XmlSectionHelper
{
SimpleXMLWriter & parent;
bool state;
public:
XmlSectionHelper(SimpleXMLWriter & a_parent, const string & tag) : parent(a_parent state(false)
{
parent.begin_section(tag);
}
~XmlSectionHelper
{
parent.end_section;
}
bool loop_test
{
state = !state;
return state; // returns true first time, false second time.
}
};
#define XML_SECTION(xml, ...) for (XmlSectionHelper __xml_section_helper(xml, __VA_ARGS__); __xml_section_helper.loop_test;)
int main
{
SimpleXMLWriter xml;
XML_SECTION(xml, "lulz1")
{
xml.write_value("key1", "value1");
XML_SECTION(xml, "lulz2")
{
xml.write_value("key2", "value2");
}
xml.write_value("key3", "value3");
}
}
__xml_section_helperсовременные компиляторы с намёками static analysis будут ругаться на то что одну и ту же переменную заново определяешь - т.е. MSVC10 будет 100%, но мне кажется что также и свежий gcc, не говоря уж про clang.
некоторые компиляторы (типа древнего MSVC6, но не только!) вообще не скомпилируют т.к. в них scope переменной объявленной в цикле for не ограничен телом цикла.
можно попробовать генерить имя переменной как-то так:
#define CONCATENATE_DIRECT(s1, s2) s1##s2
#define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
#define XML_SECTION(xml, ...) for (XmlSectionHelper ANONYMOUS_VARIABLE(__xml_section_helperxml, __VA_ARGS__); ANONYMOUS_VARIABLE(__xml_section_helper).loop_test;)
#define XML_SECTION(xml, ...) if (XmlSectionHelper __xml_section_helper = XmlSectionHelper(xml, __VA_ARGS__
только operator bool надо задекларировать.
При этом такое не компилируется
#define XML_SECTION(xml, ...) if (XmlSectionHelper __xml_section_helper(xml, __VA_ARGS__
и такое тоже
#define XML_SECTION(xml, ...) if (XmlSectionHelper __xml_section_helper = XmlSectionHelper(xml, __VA_ARGS__ *dummy = (XmlSectionHelper*)1)
Странный язык...
современные компиляторы с намёками static analysis будут ругаться на то что одну и ту же переменную заново определяешь - т.е. MSVC10 будет 100%, но мне кажется что также и свежий gcc, не говоря уж про clang.MSVC-то понятно, но компиляторы C++-то, вроде, имеют представление об области видимости.
MSVC-то понятно, но компиляторы C++-то, вроде, имеют представление об области видимости.в MSVC >= 1310 (2003 т.е.) с этим в порядке.
однако автор activemq-cpp (с которой мне приходится иметь дело принципиально шлющий нафиг с древними MSVC, тем не менее данной проблемой озаботился и написал макрос чуть по-другому, из чего я делаю вывод что не только у MSVC такие баги бывают.
/**
* The synchronized macro defines a mechanism for synchronizing
* a section of code. The macro must be passed an object that
* implements the Synchronizable interface.
*
* The macro works by creating a for loop that will loop exactly
* once, creating a Lock object that is scoped to the loop. Once
* the loop completes and exits the Lock object goes out of scope
* releasing the lock on object W. For added safety the if else
* is used because not all compiles restrict the lifetime of
* loop variables to the loop, they will however restrict them
* to the scope of the else.
*
* The macro would be used as follows.
*
* Synchronizable X;
*
* somefunction
* {
* synchronized(X)
* {
* // Do something that needs synchronizing.
* }
* }
*/
#define synchronized(W) \
if(false){} \
else \
for( decaf::util::concurrent::Lock lock_W(W); \
lock_W.isLocked; lock_W.unlock )
современные компиляторы с намёками static analysis будут ругаться на то что одну и ту же переменную заново определяешь - т.е. MSVC10 будет 100%, но мне кажется что также и свежий gcc, не говоря уж про clang.
Я проверял на ideone.com, у них весьма дико свежий гцц, и не ругается.
Прозреваю что потому, что BOOST_FOREACH заимплементен похожим образом, и у тебя должна быть возможность сказать
BOOST_FOREACH(xtype & x, xs) BOOST_FOREACH(ytype & y, ys)
{
...
}
Они наверное могли бы использовать __LINE__ но у них тогда бы всё наебнулось бы точно так же если бы компиляторы выдавали варнинги на эту тему. Boost > compilers, поэтому те молчат в тряпочку.
Про MSVC 6.0 я знаю, но могу положить МПХ к счастью, из древних компиляторов меня только GCC 2.9 (кажется) и 3.4 заботят, к счастью. И то, первый — редко. Хотя показанный Vond'ом подход я запомнил, вдруг пригодится.
Объявление переменной внутри if дичайше нестандартно же, не? Влом читать стандарт. И не нужно, ибо всё равно надобно определить оператор тайпкаста, я лучше явно функцию определю, мне в моём подходе нравится практически полное отсутствие чорной магеи (я тут недавно портировал код который писал два года назад, блядь, как я того мудака ненавижу!)
современные компиляторы с намёками static analysis будут ругаться на то что одну и ту же переменную заново определяешьЭто же разные переменные. Можно ругаться на перекрытие имен, но это зависит от флагов компиляции.
включённый static analyzer в MSVC10 с флагами по-умолчанию ругается
современные компиляторы с намёками static analysis будут ругаться на то что одну и ту же переменную заново определяешь - т.е. MSVC10 будет 100%, но мне кажется что также и свежий gcc, не говоря уж про clang.вот такой код компилируется без предупреждений\ошибок в VS2010 + /W4 (или /Wall)
int f = 0;
{
int f = 0;
if (int f = 9)
{
f = 10;
}
f = 1;
}
f = 8;
Объявление переменной внутри if дичайше нестандартно же, не?вполне себе стандартно
неверное утверждение, которое легко проверяется.я уже два раза написал - "static analyzer"
вот /W4 почему-то никогда не включал, а static analyzer - всегда когда архитектура позволяет (в msvc10 он только с x86)
выглядит вот так:
1>...\pgexecrules.cpp(103): warning C6246: Local declaration of 'it' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '88' of '...\pgexecrules.cpp': Lines: 88
я уже два раза написал - "static analyzer"никогда не юзал эту шнягу =\
оказывается, и не поюзаю, ибо
Code Analysis can be found in the Premium and Ultimate editions of Visual Studio 2010.
Однако пишут что и с Professional тоже можно как-то использовать, например:
http://www.iprogrammable.com/2011/06/15/visual-studio-2010-p...
FxCop is a standalone Code Analysis version that comes together with “Microsoft Windows SDK for Windows 7 and .NET Framework 4 Version 7.1”
Кстати, в vc11 (aka Visual Studio 2012) его включили во всех варианты студии:
- с полным набором правил начиная с Pro и дороже;
- выборочно с ключевыми правилами даже в Express.
http://blogs.msdn.com/b/codeanalysis/archive/2012/03/09/what...
Во, кстати John Carmack рекламирует микрософтовский /analyze: http://www.altdevblogaday.com/2011/12/24/static-code-analysi...
Оставить комментарий
bleyman
Типа, кот: http://ideone.com/Oav40Хочется наколенную хрень чтобы например писать дико простой XML. Например. В наколенной хрени хочется автоматически закрывать тэги. Чтобы например пишешь xml.section("asd" оно фигачит открывающий тэг, и автоматически фигачит закрывающий тэг в конце scope.
Проблема в том, что по ходу если ты создаёшь безымянный временный объект, то он убивается сразу, а не в конце scope. Вот как в примере по ссылке, XmlSection section(xml, "asd"); работает как я хочу, XmlSection(xml, "asd"); убивается сразу.
Я перед этим написал ещё более стрёмный код где реально xml.section("asd") возвращало специальный экземпляр приватного класса (пришлось в результате использовать слово mutable! но он точно так же убивался сразу.
Типа, так нельзя делать ваще, да?
А может как-нибудь по-другому можно лучше сделать? Так довольно странно получается что структура кода не повторяет структуру эксемельки, код плоский, а та — нестится, может как-нибудь сделать стрёмный макрос наподобие BOOST_FOREACH, чтобы писать