From a1589bec787923eb0358d77b5096cd8287c8528f Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 5 Apr 2013 21:03:07 +0000 Subject: GCC 4.6 workaround for vector of objects with consts Make options much more flexible with Boost function interface --- project2/cgi/cgiContentNegotiate.cpp | 18 +++-- project2/cgi/cgiProgRouter.cpp | 11 ++- project2/common/options.cpp | 25 +++++- project2/common/options.h | 138 ++++++++------------------------ project2/console/consoleEnvironment.cpp | 16 ++-- project2/json/couchSession.cpp | 4 +- 6 files changed, 84 insertions(+), 128 deletions(-) diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp index 176441e..2ed54c9 100644 --- a/project2/cgi/cgiContentNegotiate.cpp +++ b/project2/cgi/cgiContentNegotiate.cpp @@ -10,11 +10,13 @@ class ContentNegotiateLoader : public PresenterLoader { opts("Content negotiation options") { opts - ("cgi.contentnegotiation.mappedtype", Options::value(&mappedTypes), + ("cgi.contentnegotiation.mappedtype", Options::functions( + [this](const VariableType & v) { mappedTypes.push_back(new MappedType(v)); }, + boost::bind(&MappedTypes::clear, &mappedTypes)), "mimetype=presenter list of types to negotiate") ; } - + const Options * options() const { return &opts; } MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const @@ -25,16 +27,16 @@ class ContentNegotiateLoader : public PresenterLoader { const auto mimetype = mimetypeAndWeight.substr(0, mimetypeAndWeight.find(';')); if (mimetype == "*/*") break; BOOST_FOREACH(const auto & t, mappedTypes) { - if (t.Matches(mimetype)) { - return PresenterLoader::getFor(t.present)->create(s, os); + if (t->Matches(mimetype)) { + return PresenterLoader::getFor(t->present)->create(s, os); } } } - return PresenterLoader::getFor(mappedTypes.begin()->present)->create(s, os); + return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os); } Options opts; - class MappedType { + class MappedType : public IntrusivePtrBase { public: MappedType(const std::string & val) : accept(val.substr(0, val.find('='))), @@ -50,7 +52,9 @@ class ContentNegotiateLoader : public PresenterLoader { const std::string accept; const std::string present; }; - std::vector mappedTypes; + typedef boost::intrusive_ptr MappedTypePtr; + typedef std::vector MappedTypes; + MappedTypes mappedTypes; bool cacheable() const { return false; } }; diff --git a/project2/cgi/cgiProgRouter.cpp b/project2/cgi/cgiProgRouter.cpp index d094598..932242e 100644 --- a/project2/cgi/cgiProgRouter.cpp +++ b/project2/cgi/cgiProgRouter.cpp @@ -12,7 +12,7 @@ typedef std::map VarMap; class RoutingTable { public: - RoutingTable & operator=(const std::string & routeFile) { + void loadRoutesFromFile(const std::string & routeFile) { routeScriptPath = routeFile; if (routeFile.empty()) { routes.clear(); @@ -21,7 +21,10 @@ class RoutingTable { else { setRouteScript(); } - return *this; + } + + void clearRoutes() { + routes.clear(); } void onBefore() @@ -128,7 +131,9 @@ class ProgRouterLoader : public RouterLoader::For { opts("CGI Prog Router options") { opts - ("cgi.progRouter.routes", Options::value(&routingTable), + ("cgi.progRouter.routes", Options::functions( + boost::bind(&RoutingTable::loadRoutesFromFile, &routingTable, _1), + boost::bind(&RoutingTable::clearRoutes, &routingTable)), "Script file defining web service routes") ; } diff --git a/project2/common/options.cpp b/project2/common/options.cpp index 13e189b..b2777fa 100644 --- a/project2/common/options.cpp +++ b/project2/common/options.cpp @@ -125,11 +125,19 @@ Options::find(const Glib::ustring & n) const { return NULL; } -Options::InstanceTarget::InstanceTarget() : - ts(Default) +Options::InstanceTarget::InstanceTarget(const Assigner & a, const Resetter & r) : + ts(Default), + assigner(a), + resetter(r) { } +bool +Options::InstanceTarget::paramRequired() const +{ + return true; +} + void Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v) const { @@ -143,3 +151,16 @@ Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v } } +void +Options::InstanceTarget::reset() const +{ + ts = Default; + resetter(); +} + +void +Options::InstanceTarget::assign(const VariableType & value) const +{ + assigner(value); +} + diff --git a/project2/common/options.h b/project2/common/options.h index 8b9e9a0..b336854 100644 --- a/project2/common/options.h +++ b/project2/common/options.h @@ -5,34 +5,11 @@ #include #include #include -#include +#include +#include #include #include "variableType.h" -#if !__GNUC_PREREQ(4,7) -// If gcc_version >= 4.0 -namespace std { - // - // Should be part of the standard headers, but seems to be missing - // - template - class __is_assignable_helper : public __sfinae_types { - template - static decltype(declval<_Tp1>() = declval<_Up1>(), __one()) __test(int); - - template - static __two __test(...); - - public: - static constexpr bool value = sizeof(__test<_Tp, _Up>(0)) == 1; - }; - /// is_assignable - template - struct is_assignable : public integral_constant::value> - { }; -} -#endif - class Options { public: class Target; @@ -45,83 +22,20 @@ class Options { virtual void consume(const Glib::ustring & platform, const VariableType & value) const = 0; }; typedef boost::intrusive_ptr TargetPtr; + typedef boost::function Assigner; + typedef boost::function Resetter; class InstanceTarget : public Target { public: - InstanceTarget(); - bool paramRequired() const { - return true; - } + InstanceTarget(const Assigner &, const Resetter &); + bool paramRequired() const; void consume(const Glib::ustring & platform, const VariableType & value) const; protected: - virtual void assign(const VariableType & value) const = 0; + void reset() const; + void assign(const VariableType & value) const; mutable TargetState ts; - }; - - template class TypedTarget : public InstanceTarget { - public: - TypedTarget(T * t, const D & d) : - target(t), - defValue(d) { - } - TypedTarget(T * t) : - target(t), - defValue(T()) { - } - void reset() const { - ts = Default; - *target = defValue; - } - void assign(const VariableType & value) const { - doAssign(value); - } - protected: - T * target; - private: - template - void doAssign(const VariableType & value, - typename boost::disable_if, dummy>::type = 0, - typename boost::disable_if, dummy>::type = 0) const { - *target = boost::lexical_cast(value.as()); - } - template - void doAssign(const VariableType & value, - typename boost::enable_if, dummy>::type = 0) const { - *target = value.as(); - } - template - void doAssign(const VariableType & value, - typename boost::disable_if, dummy>::type = 0, - typename boost::enable_if, dummy>::type = 0) const { - *target = value; - } - D defValue; - }; - - template class TypedTarget > : public InstanceTarget { - public: - typedef std::vector VofT; - TypedTarget(VofT * t) : - target(t) { - } - void reset() const { - ts = Default; - target->clear(); - } - void assign(const VariableType & value) const { - doAssign(value); - } - protected: - VofT * target; - private: - template - void doAssign(const VariableType & value, typename boost::disable_if, dummy>::type = 0) const { - target->push_back(boost::lexical_cast(value.as())); - } - template - void doAssign(const VariableType & value, typename boost::enable_if, dummy>::type = 0) const { - target->push_back(T(value)); - } + Assigner assigner; + Resetter resetter; }; class Option : public IntrusivePtrBase { @@ -140,20 +54,34 @@ class Options { Options & operator()(const Glib::ustring & optionName, TargetPtr target, const Glib::ustring & description); Options & operator()(const Glib::ustring & optionName); Options & operator()(OptionPtr); - template + + template static - TargetPtr value(T * t) { - return new TypedTarget(t); + TargetPtr value(T * t, const D & d = D(), + typename boost::enable_if, dummy>::type = 0) { + return new InstanceTarget( + [t](const VariableType & v) { *t = v.as(); }, + [t, d]() { *t = d; }); } - template + + template static - TargetPtr value(T * t, const D & d) { - return new TypedTarget(t, d); + TargetPtr value(T * t, const D & d = D(), + typename boost::disable_if, dummy>::type = 0) { + return new InstanceTarget( + [t](const VariableType & v) { *t = v; }, + [t, d]() { *t = d; }); } - template + + template + static + TargetPtr function(const Assigner & assigner, const D & d) { + return new InstanceTarget(assigner, boost::bind(assigner, d)); + } + static - TargetPtr valueConvert(T * t, const D & d) { - return new TypedTarget(t, d); + TargetPtr functions(const Assigner & assigner, const Resetter & resetter) { + return new InstanceTarget(assigner, resetter); } void reset() const; diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index 2420e35..28da574 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -17,15 +17,6 @@ int ConsoleEnvironment::argc; char ** ConsoleEnvironment::argv; ConsoleEnvironment::ToDoList ConsoleEnvironment::todolist; -template -std::basic_istream<_CharT, _Traits> & -operator>>(std::basic_istream<_CharT, _Traits> & s, ConsoleEnvironment::QueryParams::value_type & q) -{ - std::getline(s, q.first, '='); - std::getline(s, q.second); - return s; -} - class ShowHelpTrigger : public Options::Target { public: void reset() const { } @@ -48,7 +39,12 @@ ConsoleEnvironment::ConsoleEnvironment(int c, char ** v) : ("help", new ShowHelpTrigger(), "Print usage and exit")("h") ("console.syslogIdent", Options::value(&scriptname, scriptname), "Log to syslog with ident ") ("console.platform", Options::value(&reqPlatform), "Platform")("p") - ("console.queryParam", Options::value(&queryParams), "Query parameter")("q") + ("console.queryParam", Options::functions( + [this](const VariableType & v) { + Glib::ustring vs(v.as()); + queryParams.push_back(QueryParams::value_type(vs.substr(0, vs.find('=')), vs.substr(vs.find('=') + 1))); + }, + boost::bind(&QueryParams::clear, &queryParams)), "Query parameter")("q") ; } diff --git a/project2/json/couchSession.cpp b/project2/json/couchSession.cpp index 7045113..2fe2ae6 100644 --- a/project2/json/couchSession.cpp +++ b/project2/json/couchSession.cpp @@ -111,7 +111,9 @@ class CustomCouchSessionLoader : public SessionContainerLoader::For::clear, &CouchSessionContainer::baseUrls)), "Base URL to store sessions in") ; } -- cgit v1.2.3